1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "animation/rs_animation_fraction.h"
17
18 #include <cstdlib>
19 #include <cstring>
20 #include <string>
21
22 #include "common/rs_common_def.h"
23 #include "platform/common/rs_log.h"
24 #include "platform/common/rs_system_properties.h"
25
26 namespace OHOS {
27 namespace Rosen {
28 namespace {
29 static constexpr int INFINITE = -1;
30 static constexpr int64_t MS_TO_NS = 1000000;
31 static constexpr int REVERSE_COUNT = 2;
32 static constexpr int MAX_SPEED = 1000000;
33 constexpr const char* ANIMATION_SCALE_NAME = "persist.sys.graphic.animationscale";
34 } // namespace
35
36 bool RSAnimationFraction::isInited_ = false;
37 float RSAnimationFraction::animationScale_ = 1.0f;
38 std::mutex RSAnimationFraction::mutex_;
39
RSAnimationFraction()40 RSAnimationFraction::RSAnimationFraction()
41 {
42 currentIsReverseCycle_ = !isForward_;
43 }
44
Init()45 void RSAnimationFraction::Init()
46 {
47 if (!isInited_) {
48 SetAnimationScale(RSSystemProperties::GetAnimationScale());
49 RSSystemProperties::WatchSystemProperty(ANIMATION_SCALE_NAME, OnAnimationScaleChangedCallback, nullptr);
50 isInited_ = true;
51 }
52 }
53
GetAnimationScale()54 float RSAnimationFraction::GetAnimationScale()
55 {
56 std::lock_guard<std::mutex> lock(mutex_);
57 return animationScale_;
58 }
59
SetAnimationScale(float animationScale)60 void RSAnimationFraction::SetAnimationScale(float animationScale)
61 {
62 std::lock_guard<std::mutex> lock(mutex_);
63 animationScale_ = animationScale < 0.0 ? 0.0 : animationScale;
64 }
65
OnAnimationScaleChangedCallback(const char * key,const char * value,void * context)66 void RSAnimationFraction::OnAnimationScaleChangedCallback(const char *key, const char *value, void *context)
67 {
68 if (strcmp(key, ANIMATION_SCALE_NAME) != 0) {
69 return;
70 }
71 float animationScale = std::atof(value);
72 SetAnimationScale(animationScale);
73 }
74
SetDirectionAfterStart(const ForwardDirection & direction)75 void RSAnimationFraction::SetDirectionAfterStart(const ForwardDirection& direction)
76 {
77 direction_ = direction;
78 }
79
SetLastFrameTime(int64_t lastFrameTime)80 void RSAnimationFraction::SetLastFrameTime(int64_t lastFrameTime)
81 {
82 lastFrameTime_ = lastFrameTime;
83 }
84
GetLastFrameTime() const85 int64_t RSAnimationFraction::GetLastFrameTime() const
86 {
87 return lastFrameTime_;
88 }
89
GetAnimationFraction(int64_t time,bool & isInstartDelay,bool & isFinished)90 float RSAnimationFraction::GetAnimationFraction(int64_t time, bool& isInstartDelay, bool& isFinished)
91 {
92 int64_t durationNs = duration_ * MS_TO_NS;
93 int64_t startDelayNs = startDelay_ * MS_TO_NS;
94 int64_t deltaTime = time - lastFrameTime_;
95 lastFrameTime_ = time;
96 isInstartDelay = false;
97 if (durationNs <= 0 || (repeatCount_ <= 0 && repeatCount_ != INFINITE)) {
98 isFinished = true;
99 return GetEndFraction();
100 }
101 // 1. Calculates the total running fraction of animation
102 float animationScale = GetAnimationScale();
103 if (direction_ == ForwardDirection::NORMAL) {
104 if (animationScale == 0.0) {
105 runningTime_ += static_cast<int64_t>(deltaTime * MAX_SPEED);
106 } else {
107 runningTime_ += static_cast<int64_t>(deltaTime * speed_ / animationScale);
108 }
109 } else {
110 if (animationScale == 0.0) {
111 runningTime_ -= static_cast<int64_t>(deltaTime * MAX_SPEED);
112 } else {
113 runningTime_ -= static_cast<int64_t>(deltaTime * speed_ / animationScale);
114 }
115 }
116 if (runningTime_ < startDelayNs) {
117 isFinished = IsFinished();
118 isInstartDelay = isFinished ? false : true;
119 return GetStartFraction();
120 }
121
122 // 2. Calculate the running time of the current cycle animation.
123 int64_t realPlayTime = runningTime_ - startDelayNs - (curRepeatCount_ * durationNs);
124
125 // 3. Update the number of cycles and the corresponding animation fraction.
126 if (direction_ == ForwardDirection::NORMAL) {
127 curRepeatCount_ += realPlayTime / durationNs;
128 } else {
129 while (curRepeatCount_ > 0 && realPlayTime < 0) {
130 curRepeatCount_--;
131 realPlayTime += durationNs;
132 }
133 }
134 playTime_ = realPlayTime % durationNs;
135
136 // 4. update status for auto reverse
137 isFinished = IsFinished();
138 UpdateReverseState(isFinished);
139
140 // 5. get final animation fraction
141 if (isFinished) {
142 return GetEndFraction();
143 }
144 curTimeFraction_ = static_cast<float>(playTime_) / durationNs;
145 curTimeFraction_ = currentIsReverseCycle_ ? (1.0f - curTimeFraction_) : curTimeFraction_;
146 curTimeFraction_ = std::min(std::max(curTimeFraction_, 0.0f), 1.0f);
147 return curTimeFraction_;
148 }
149
IsFinished() const150 bool RSAnimationFraction::IsFinished() const
151 {
152 if (direction_ == ForwardDirection::NORMAL) {
153 if (repeatCount_ == INFINITE) {
154 return false;
155 }
156 int64_t totalDuration = (duration_ * repeatCount_ + startDelay_) * MS_TO_NS;
157 return runningTime_ >= totalDuration;
158 } else {
159 return runningTime_ <= 0;
160 }
161 }
162
GetStartFraction() const163 float RSAnimationFraction::GetStartFraction() const
164 {
165 return isForward_ ? 0.0f : 1.0f;
166 }
167
GetEndFraction() const168 float RSAnimationFraction::GetEndFraction() const
169 {
170 float endFraction = 1.0f;
171 if ((autoReverse_ && repeatCount_ % REVERSE_COUNT == 0) || direction_ == ForwardDirection::REVERSE) {
172 endFraction = 0.0f;
173 }
174 endFraction = isForward_ ? endFraction : 1.0 - endFraction;
175 return endFraction;
176 }
177
UpdateReverseState(bool finish)178 void RSAnimationFraction::UpdateReverseState(bool finish)
179 {
180 if (isForward_) {
181 if (!autoReverse_) {
182 currentIsReverseCycle_ = false;
183 return;
184 }
185 currentIsReverseCycle_ =
186 finish ? (curRepeatCount_ % REVERSE_COUNT == 0) : (curRepeatCount_ % REVERSE_COUNT == 1);
187 } else {
188 if (!autoReverse_) {
189 currentIsReverseCycle_ = true;
190 return;
191 }
192 currentIsReverseCycle_ =
193 finish ? (curRepeatCount_ % REVERSE_COUNT == 1) : (curRepeatCount_ % REVERSE_COUNT == 0);
194 }
195 }
196
UpdateRemainTimeFraction(float fraction,int remainTime)197 void RSAnimationFraction::UpdateRemainTimeFraction(float fraction, int remainTime)
198 {
199 int64_t remainTimeNS = remainTime * MS_TO_NS;
200 int64_t durationNs = duration_ * MS_TO_NS;
201 int64_t startDelayNs = startDelay_ * MS_TO_NS;
202 float curRemainProgress = currentIsReverseCycle_ ? curTimeFraction_ : (1.0f - curTimeFraction_);
203 float ratio = 1.0f;
204 if (remainTime != 0) {
205 ratio = curRemainProgress * durationNs / remainTimeNS;
206 }
207
208 if (runningTime_ > startDelayNs || fabs(fraction) > 1e-6) {
209 if (currentIsReverseCycle_) {
210 runningTime_ =
211 static_cast<int64_t>(durationNs * (1.0f - fraction)) + startDelayNs + curRepeatCount_ * durationNs;
212 } else {
213 runningTime_ = static_cast<int64_t>(durationNs * fraction) + startDelayNs + curRepeatCount_ * durationNs;
214 }
215 }
216
217 speed_ = speed_ * ratio;
218 curTimeFraction_ = fraction;
219 }
220 } // namespace Rosen
221 } // namespace OHOS
222