1/*
2 * Copyright (C) 2018 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "AnimationEffect.h"
29#include "CSSPropertyBlendingClient.h"
30#include "CompositeOperation.h"
31#include "CompositeOperationOrAuto.h"
32#include "EffectTiming.h"
33#include "Element.h"
34#include "IterationCompositeOperation.h"
35#include "KeyframeEffectOptions.h"
36#include "KeyframeList.h"
37#include "RenderStyle.h"
38#include "StyleProperties.h"
39#include "WebAnimationUtilities.h"
40#include <wtf/Ref.h>
41
42namespace WebCore {
43
44class Element;
45class FilterOperations;
46
47class KeyframeEffect : public AnimationEffect
48 , public CSSPropertyBlendingClient {
49public:
50 static ExceptionOr<Ref<KeyframeEffect>> create(JSC::ExecState&, Element*, JSC::Strong<JSC::JSObject>&&, Optional<Variant<double, KeyframeEffectOptions>>&&);
51 static ExceptionOr<Ref<KeyframeEffect>> create(JSC::ExecState&, Ref<KeyframeEffect>&&);
52 static Ref<KeyframeEffect> create(const Element&);
53 ~KeyframeEffect() { }
54
55 bool isKeyframeEffect() const final { return true; }
56
57 struct BasePropertyIndexedKeyframe {
58 Variant<std::nullptr_t, Vector<Optional<double>>, double> offset = Vector<Optional<double>>();
59 Variant<Vector<String>, String> easing = Vector<String>();
60 Variant<Vector<CompositeOperationOrAuto>, CompositeOperationOrAuto> composite = Vector<CompositeOperationOrAuto>();
61 };
62
63 struct BaseKeyframe {
64 MarkableDouble offset;
65 String easing { "linear" };
66 CompositeOperationOrAuto composite { CompositeOperationOrAuto::Auto };
67 };
68
69 struct PropertyAndValues {
70 CSSPropertyID property;
71 Vector<String> values;
72 };
73
74 struct KeyframeLikeObject {
75 BasePropertyIndexedKeyframe baseProperties;
76 Vector<PropertyAndValues> propertiesAndValues;
77 };
78
79 struct ParsedKeyframe {
80 MarkableDouble offset;
81 double computedOffset;
82 CompositeOperationOrAuto composite { CompositeOperationOrAuto::Auto };
83 String easing;
84 RefPtr<TimingFunction> timingFunction;
85 Ref<MutableStyleProperties> style;
86 HashMap<CSSPropertyID, String> unparsedStyle;
87
88 ParsedKeyframe()
89 : style(MutableStyleProperties::create())
90 {
91 }
92 };
93
94 struct BaseComputedKeyframe {
95 MarkableDouble offset;
96 double computedOffset;
97 String easing { "linear" };
98 CompositeOperationOrAuto composite { CompositeOperationOrAuto::Auto };
99 };
100
101 Element* target() const { return m_target.get(); }
102 void setTarget(RefPtr<Element>&&);
103
104 Vector<JSC::Strong<JSC::JSObject>> getKeyframes(JSC::ExecState&);
105 ExceptionOr<void> setKeyframes(JSC::ExecState&, JSC::Strong<JSC::JSObject>&&);
106
107 IterationCompositeOperation iterationComposite() const { return m_iterationCompositeOperation; }
108 void setIterationComposite(IterationCompositeOperation iterationCompositeOperation) { m_iterationCompositeOperation = iterationCompositeOperation; }
109 CompositeOperation composite() const { return m_compositeOperation; }
110 void setComposite(CompositeOperation compositeOperation) { m_compositeOperation = compositeOperation; }
111
112 void getAnimatedStyle(std::unique_ptr<RenderStyle>& animatedStyle);
113 void apply(RenderStyle&) override;
114 void invalidate() override;
115 void animationDidSeek() final;
116 void animationSuspensionStateDidChange(bool) final;
117 void applyPendingAcceleratedActions();
118 bool isRunningAccelerated() const { return m_lastRecordedAcceleratedAction != AcceleratedAction::Stop; }
119 bool hasPendingAcceleratedAction() const { return !m_pendingAcceleratedActions.isEmpty() && isRunningAccelerated(); }
120
121 RenderElement* renderer() const override;
122 const RenderStyle& currentStyle() const override;
123 bool isAccelerated() const override { return m_shouldRunAccelerated; }
124 bool filterFunctionListsMatch() const override { return m_filterFunctionListsMatch; }
125 bool transformFunctionListsMatch() const override { return m_transformFunctionListsMatch; }
126#if ENABLE(FILTERS_LEVEL_2)
127 bool backdropFilterFunctionListsMatch() const override { return m_backdropFilterFunctionListsMatch; }
128#endif
129 bool colorFilterFunctionListsMatch() const override { return m_colorFilterFunctionListsMatch; }
130
131 void computeDeclarativeAnimationBlendingKeyframes(const RenderStyle* oldStyle, const RenderStyle& newStyle);
132 bool hasBlendingKeyframes() const { return m_blendingKeyframes.size(); }
133 const HashSet<CSSPropertyID>& animatedProperties() const { return m_blendingKeyframes.properties(); }
134
135 bool computeExtentOfTransformAnimation(LayoutRect&) const;
136 bool computeTransformedExtentViaTransformList(const FloatRect&, const RenderStyle&, LayoutRect&) const;
137 bool computeTransformedExtentViaMatrix(const FloatRect&, const RenderStyle&, LayoutRect&) const;
138 bool forceLayoutIfNeeded();
139
140private:
141 KeyframeEffect(Element*);
142
143 enum class AcceleratedAction : uint8_t { Play, Pause, Seek, Stop };
144
145 void copyPropertiesFromSource(Ref<KeyframeEffect>&&);
146 ExceptionOr<void> processKeyframes(JSC::ExecState&, JSC::Strong<JSC::JSObject>&&);
147 void addPendingAcceleratedAction(AcceleratedAction);
148 void updateAcceleratedAnimationState();
149 void setAnimatedPropertiesInStyle(RenderStyle&, double);
150 TimingFunction* timingFunctionForKeyframeAtIndex(size_t);
151 Ref<const Animation> backingAnimationForCompositedRenderer() const;
152 void computedNeedsForcedLayout();
153 void computeStackingContextImpact();
154 void updateBlendingKeyframes(RenderStyle&);
155 void computeCSSAnimationBlendingKeyframes();
156 void computeCSSTransitionBlendingKeyframes(const RenderStyle* oldStyle, const RenderStyle& newStyle);
157 void computeShouldRunAccelerated();
158 void setBlendingKeyframes(KeyframeList&);
159 void checkForMatchingTransformFunctionLists();
160 void checkForMatchingFilterFunctionLists();
161 void checkForMatchingColorFilterFunctionLists();
162 bool checkForMatchingFilterFunctionLists(CSSPropertyID, const std::function<const FilterOperations& (const RenderStyle&)>&) const;
163#if ENABLE(FILTERS_LEVEL_2)
164 void checkForMatchingBackdropFilterFunctionLists();
165#endif
166
167 KeyframeList m_blendingKeyframes { emptyString() };
168 Vector<ParsedKeyframe> m_parsedKeyframes;
169 Vector<AcceleratedAction> m_pendingAcceleratedActions;
170 RefPtr<Element> m_target;
171
172 AcceleratedAction m_lastRecordedAcceleratedAction { AcceleratedAction::Stop };
173 IterationCompositeOperation m_iterationCompositeOperation { IterationCompositeOperation::Replace };
174 CompositeOperation m_compositeOperation { CompositeOperation::Replace };
175 bool m_shouldRunAccelerated { false };
176 bool m_needsForcedLayout { false };
177 bool m_triggersStackingContext { false };
178 bool m_transformFunctionListsMatch { false };
179 bool m_filterFunctionListsMatch { false };
180#if ENABLE(FILTERS_LEVEL_2)
181 bool m_backdropFilterFunctionListsMatch { false };
182#endif
183 bool m_colorFilterFunctionListsMatch { false };
184};
185
186} // namespace WebCore
187
188SPECIALIZE_TYPE_TRAITS_ANIMATION_EFFECT(KeyframeEffect, isKeyframeEffect());
189