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