1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.h"
6 #include "third_party/blink/renderer/bindings/core/v8/v8_computed_effect_timing.h"
7 #include "third_party/blink/renderer/core/animation/timing_calculations.h"
8 
9 namespace blink {
10 
WorkletAnimationEffect(base::Optional<base::TimeDelta> local_time,const Timing & specified_timing)11 WorkletAnimationEffect::WorkletAnimationEffect(
12     base::Optional<base::TimeDelta> local_time,
13     const Timing& specified_timing)
14     : local_time_(local_time),
15       specified_timing_(specified_timing),
16       calculated_() {
17   specified_timing_.AssertValid();
18 }
19 
getTiming() const20 EffectTiming* WorkletAnimationEffect::getTiming() const {
21   return specified_timing_.ConvertToEffectTiming();
22 }
23 
getComputedTiming() const24 ComputedEffectTiming* WorkletAnimationEffect::getComputedTiming() const {
25   base::Optional<double> local_time;
26   if (local_time_)
27     local_time = base::Optional<double>(local_time_.value().InSecondsF());
28 
29   bool needs_update = last_update_time_ != local_time;
30   last_update_time_ = local_time;
31 
32   if (needs_update) {
33     // The playback rate is needed to calculate whether the effect is current or
34     // not (https://drafts.csswg.org/web-animations-1/#current). Since we only
35     // use this information to create a ComputedEffectTiming, which does not
36     // include that information, we do not need to supply one.
37     base::Optional<double> playback_rate = base::nullopt;
38     calculated_ = specified_timing_.CalculateTimings(
39         local_time, Timing::AnimationDirection::kForwards, false,
40         playback_rate);
41   }
42 
43   return specified_timing_.getComputedTiming(calculated_,
44                                              /*is_keyframe_effect*/ false);
45 }
46 
localTime() const47 base::Optional<double> WorkletAnimationEffect::localTime() const {
48   if (!local_time_)
49     return base::nullopt;
50   return local_time_.value().InMillisecondsF();
51 }
52 
setLocalTime(base::Optional<double> time_ms)53 void WorkletAnimationEffect::setLocalTime(base::Optional<double> time_ms) {
54   if (!time_ms) {
55     local_time_.reset();
56     return;
57   }
58   DCHECK(!std::isnan(time_ms.value()));
59   // Convert double to base::TimeDelta because cc/animation expects
60   // base::TimeDelta.
61   //
62   // Note on precision loss: base::TimeDelta has microseconds precision which is
63   // also the precision recommended by the web animation specification as well
64   // [1]. If the input time value has a bigger precision then the conversion
65   // causes precision loss. Doing the conversion here ensures that reading the
66   // value back provides the actual value we use in further computation which
67   // is the least surprising path.
68   // [1] https://drafts.csswg.org/web-animations/#precision-of-time-values
69   local_time_ = base::TimeDelta::FromMillisecondsD(time_ms.value());
70 }
71 
setLocalTime(double time_ms,bool is_null)72 void WorkletAnimationEffect::setLocalTime(double time_ms, bool is_null) {
73   if (is_null) {
74     local_time_.reset();
75     return;
76   }
77   DCHECK(!std::isnan(time_ms));
78   // Convert double to base::TimeDelta because cc/animation expects
79   // base::TimeDelta.
80   //
81   // Note on precision loss: base::TimeDelta has microseconds precision which is
82   // also the precision recommended by the web animation specification as well
83   // [1]. If the input time value has a bigger precision then the conversion
84   // causes precision loss. Doing the conversion here ensures that reading the
85   // value back provides the actual value we use in further computation which
86   // is the least surprising path.
87   // [1] https://drafts.csswg.org/web-animations/#precision-of-time-values
88   local_time_ = base::TimeDelta::FromMillisecondsD(time_ms);
89 }
90 
localTime(bool & is_null) const91 double WorkletAnimationEffect::localTime(bool& is_null) const {
92   is_null = !local_time_.has_value();
93   return local_time_.value_or(base::TimeDelta()).InMillisecondsF();
94 }
95 
local_time() const96 base::Optional<base::TimeDelta> WorkletAnimationEffect::local_time() const {
97   return local_time_;
98 }
99 }  // namespace blink
100