1 /*
2 * Copyright (C) 2013 Google 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 are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "third_party/blink/renderer/core/animation/element_animations.h"
32
33 #include "third_party/blink/renderer/core/css/css_property_equality.h"
34 #include "third_party/blink/renderer/core/css/properties/css_property.h"
35 #include "third_party/blink/renderer/core/style/computed_style.h"
36
37 namespace blink {
38
39 namespace {
40
UpdateAnimationFlagsForEffect(const KeyframeEffect & effect,ComputedStyle & style)41 void UpdateAnimationFlagsForEffect(const KeyframeEffect& effect,
42 ComputedStyle& style) {
43 if (effect.Affects(PropertyHandle(GetCSSPropertyOpacity())))
44 style.SetHasCurrentOpacityAnimation(true);
45 if (effect.Affects(PropertyHandle(GetCSSPropertyTransform())) ||
46 effect.Affects(PropertyHandle(GetCSSPropertyRotate())) ||
47 effect.Affects(PropertyHandle(GetCSSPropertyScale())) ||
48 effect.Affects(PropertyHandle(GetCSSPropertyTranslate())))
49 style.SetHasCurrentTransformAnimation(true);
50 if (effect.Affects(PropertyHandle(GetCSSPropertyFilter())))
51 style.SetHasCurrentFilterAnimation(true);
52 if (effect.Affects(PropertyHandle(GetCSSPropertyBackdropFilter())))
53 style.SetHasCurrentBackdropFilterAnimation(true);
54 }
55
56 } // namespace
57
ElementAnimations()58 ElementAnimations::ElementAnimations() : animation_style_change_(false) {}
59
60 ElementAnimations::~ElementAnimations() = default;
61
UpdateAnimationFlags(ComputedStyle & style)62 void ElementAnimations::UpdateAnimationFlags(ComputedStyle& style) {
63 for (const auto& entry : animations_) {
64 const Animation& animation = *entry.key;
65 DCHECK(animation.effect());
66 // FIXME: Needs to consider AnimationGroup once added.
67 DCHECK(IsA<KeyframeEffect>(animation.effect()));
68 const auto& effect = *To<KeyframeEffect>(animation.effect());
69 if (!effect.IsCurrent())
70 continue;
71 UpdateAnimationFlagsForEffect(effect, style);
72 }
73
74 for (const auto& entry : worklet_animations_) {
75 const KeyframeEffect& effect = *entry->GetEffect();
76 // TODO(majidvp): we should check the effect's phase before updating the
77 // style once the timing of effect is ready to use.
78 // https://crbug.com/814851.
79 UpdateAnimationFlagsForEffect(effect, style);
80 }
81
82 if (style.HasCurrentOpacityAnimation()) {
83 style.SetIsRunningOpacityAnimationOnCompositor(
84 effect_stack_.HasActiveAnimationsOnCompositor(
85 PropertyHandle(GetCSSPropertyOpacity())));
86 }
87 if (style.HasCurrentTransformAnimation()) {
88 style.SetIsRunningTransformAnimationOnCompositor(
89 effect_stack_.HasActiveAnimationsOnCompositor(
90 PropertyHandle(GetCSSPropertyTransform())));
91 }
92 if (style.HasCurrentFilterAnimation()) {
93 style.SetIsRunningFilterAnimationOnCompositor(
94 effect_stack_.HasActiveAnimationsOnCompositor(
95 PropertyHandle(GetCSSPropertyFilter())));
96 }
97 if (style.HasCurrentBackdropFilterAnimation()) {
98 style.SetIsRunningBackdropFilterAnimationOnCompositor(
99 effect_stack_.HasActiveAnimationsOnCompositor(
100 PropertyHandle(GetCSSPropertyBackdropFilter())));
101 }
102 }
103
RestartAnimationOnCompositor()104 void ElementAnimations::RestartAnimationOnCompositor() {
105 for (const auto& entry : animations_)
106 entry.key->RestartAnimationOnCompositor();
107 }
108
Trace(Visitor * visitor) const109 void ElementAnimations::Trace(Visitor* visitor) const {
110 visitor->Trace(css_animations_);
111 visitor->Trace(effect_stack_);
112 visitor->Trace(animations_);
113 visitor->Trace(worklet_animations_);
114 }
115
BaseComputedStyle() const116 const ComputedStyle* ElementAnimations::BaseComputedStyle() const {
117 return base_computed_style_.get();
118 }
119
BaseImportantSet() const120 const CSSBitset* ElementAnimations::BaseImportantSet() const {
121 if (IsAnimationStyleChange())
122 return base_important_set_.get();
123 return nullptr;
124 }
125
UpdateBaseComputedStyle(const ComputedStyle * computed_style,std::unique_ptr<CSSBitset> base_important_set)126 void ElementAnimations::UpdateBaseComputedStyle(
127 const ComputedStyle* computed_style,
128 std::unique_ptr<CSSBitset> base_important_set) {
129 DCHECK(computed_style);
130 base_computed_style_ = ComputedStyle::Clone(*computed_style);
131 base_important_set_ = std::move(base_important_set);
132 }
133
ClearBaseComputedStyle()134 void ElementAnimations::ClearBaseComputedStyle() {
135 base_computed_style_ = nullptr;
136 base_important_set_ = nullptr;
137 }
138
UpdateBoxSizeAndCheckTransformAxisAlignment(const FloatSize & box_size)139 bool ElementAnimations::UpdateBoxSizeAndCheckTransformAxisAlignment(
140 const FloatSize& box_size) {
141 bool preserves_axis_alignment = true;
142 for (auto& entry : animations_) {
143 Animation& animation = *entry.key;
144 if (auto* effect = DynamicTo<KeyframeEffect>(animation.effect())) {
145 if (!effect->IsCurrent() && !effect->IsInEffect())
146 continue;
147 if (!effect->UpdateBoxSizeAndCheckTransformAxisAlignment(box_size))
148 preserves_axis_alignment = false;
149 }
150 }
151 return preserves_axis_alignment;
152 }
153
154 } // namespace blink
155