1 /*
2 * Copyright (c) 2021 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_path_animation.h"
17
18 #include "animation/rs_animation_common.h"
19 #include "animation/rs_render_path_animation.h"
20 #include "platform/common/rs_log.h"
21 #include "command/rs_animation_command.h"
22 #include "transaction/rs_transaction_proxy.h"
23 #include "render/rs_path.h"
24
25 namespace OHOS {
26 namespace Rosen {
RSPathAnimation(const RSAnimatableProperty & property,const std::shared_ptr<RSPath> & animationPath)27 RSPathAnimation::RSPathAnimation(const RSAnimatableProperty& property, const std::shared_ptr<RSPath>& animationPath)
28 : RSPropertyAnimation(property), animationPath_(animationPath)
29 {
30 SetAdditive(false);
31 }
32
RSPathAnimation(const RSAnimatableProperty & property,const std::string & path,const Vector2f & startValue,const Vector2f & endValue)33 RSPathAnimation::RSPathAnimation(
34 const RSAnimatableProperty& property, const std::string& path, const Vector2f& startValue, const Vector2f& endValue)
35 : RSPathAnimation(property, PreProcessPath(path, startValue, endValue))
36 {}
37
38 const std::vector<RSAnimatableProperty> RSPathAnimation::PROP_FOR_PATH_ANIM = {
39 RSAnimatableProperty::BOUNDS_POSITION,
40 RSAnimatableProperty::FRAME_POSITION,
41 RSAnimatableProperty::TRANSLATE
42 };
43
SetTimingCurve(const RSAnimationTimingCurve & timingCurve)44 void RSPathAnimation::SetTimingCurve(const RSAnimationTimingCurve& timingCurve)
45 {
46 timingCurve_ = timingCurve;
47 }
48
GetTimingCurve() const49 const RSAnimationTimingCurve& RSPathAnimation::GetTimingCurve() const
50 {
51 return timingCurve_;
52 }
53
SetRotationMode(const RotationMode & rotationMode)54 void RSPathAnimation::SetRotationMode(const RotationMode& rotationMode)
55 {
56 if (IsStarted()) {
57 ROSEN_LOGE("Failed to enable rotate, path animation has started!");
58 return;
59 }
60
61 rotationMode_ = rotationMode;
62 }
63
GetRotationMode() const64 RotationMode RSPathAnimation::GetRotationMode() const
65 {
66 return rotationMode_;
67 }
68
SetBeginFraction(float fraction)69 void RSPathAnimation::SetBeginFraction(float fraction)
70 {
71 if (IsStarted()) {
72 ROSEN_LOGE("Failed to set begin fraction, path animation has started!");
73 return;
74 }
75
76 if (fraction < FRACTION_MIN || fraction > FRACTION_MAX || fraction > endFraction_) {
77 ROSEN_LOGE("Failed to set begin fraction, invalid value:%f", fraction);
78 return;
79 }
80
81 beginFraction_ = fraction;
82 }
83
GetBeginFraction() const84 float RSPathAnimation::GetBeginFraction() const
85 {
86 return beginFraction_;
87 }
88
SetEndFraction(float fraction)89 void RSPathAnimation::SetEndFraction(float fraction)
90 {
91 if (IsStarted()) {
92 ROSEN_LOGE("Failed to set end fraction, path animation has started!");
93 return;
94 }
95
96 if (fraction < FRACTION_MIN || fraction > FRACTION_MAX || fraction < beginFraction_) {
97 ROSEN_LOGE("Failed to set end fraction, invalid value:%f", fraction);
98 return;
99 }
100
101 endFraction_ = fraction;
102 }
103
GetEndFraction() const104 float RSPathAnimation::GetEndFraction() const
105 {
106 return endFraction_;
107 }
108
OnStart()109 void RSPathAnimation::OnStart()
110 {
111 if (!IsAnimatablePathProperty(GetProperty())) {
112 ROSEN_LOGE("Failed to start path animation, property[%d] is not supported!", static_cast<int>(GetProperty()));
113 return;
114 }
115
116 if (!animationPath_) {
117 ROSEN_LOGE("Failed to start path animation, path is null!");
118 return;
119 }
120
121 RSPropertyAnimation::OnStart();
122
123 auto target = GetTarget().lock();
124 if (target == nullptr) {
125 ROSEN_LOGE("Failed to start path animation, target is null!");
126 return;
127 }
128
129 auto interpolator = timingCurve_.GetInterpolator(GetDuration());
130 auto animation = std::make_shared<RSRenderPathAnimation>(
131 GetId(), GetProperty(), originValue_, target->stagingProperties_.GetRotation(), animationPath_);
132 animation->SetDuration(GetDuration());
133 animation->SetStartDelay(GetStartDelay());
134 animation->SetRepeatCount(GetRepeatCount());
135 animation->SetAutoReverse(GetAutoReverse());
136 animation->SetSpeed(GetSpeed());
137 animation->SetFillMode(GetFillMode());
138 animation->SetDirection(GetDirection());
139 animation->SetInterpolator(interpolator);
140 animation->SetRotationMode(GetRotationMode());
141 animation->SetBeginFraction(GetBeginFraction());
142 animation->SetEndFraction(GetEndFraction());
143 std::unique_ptr<RSCommand> command = std::make_unique<RSAnimationCreatePath>(target->GetId(), animation);
144 auto transactionProxy = RSTransactionProxy::GetInstance();
145 if (transactionProxy != nullptr) {
146 transactionProxy->AddCommand(command, target->IsRenderServiceNode());
147 if (target->NeedForcedSendToRemote()) {
148 std::unique_ptr<RSCommand> commandForRemote =
149 std::make_unique<RSAnimationCreatePath>(target->GetId(), animation);
150 transactionProxy->AddCommand(commandForRemote, true);
151 }
152 }
153 }
154
InitInterpolationValue()155 void RSPathAnimation::InitInterpolationValue()
156 {
157 if (!animationPath_) {
158 ROSEN_LOGE("Failed to update interpolation value, path is null!");
159 return;
160 }
161
162 #ifdef ROSEN_OHOS
163 animationPath_->GetPosTan(0.0f, startValue_, startTangent_);
164 animationPath_->GetPosTan(animationPath_->GetDistance(), endValue_, endTangent_);
165 byValue_ = endValue_ - startValue_;
166 #endif
167 }
168
OnUpdateStagingValue(bool isFirstStart)169 void RSPathAnimation::OnUpdateStagingValue(bool isFirstStart)
170 {
171 auto target = GetTarget().lock();
172 if (target == nullptr) {
173 ROSEN_LOGE("Failed to update staging value, target is null!");
174 return;
175 }
176
177 RSPropertyAnimation::OnUpdateStagingValue(isFirstStart);
178
179 float startTangent = 0.0f;
180 float endTangent = 0.0f;
181 switch (rotationMode_) {
182 case RotationMode::ROTATE_NONE:
183 return;
184 case RotationMode::ROTATE_AUTO:
185 startTangent = startTangent_;
186 endTangent = endTangent_;
187 break;
188 case RotationMode::ROTATE_AUTO_REVERSE:
189 startTangent = startTangent_ + 180.0f;
190 endTangent = endTangent_ + 180.0f;
191 break;
192 default:
193 ROSEN_LOGE("Unknow rotation mode!");
194 return;
195 }
196 if (!GetDirection()) {
197 std::swap(startTangent, endTangent);
198 }
199
200 float targetRotation = 0.0f;
201 float byRotation = endTangent - startTangent;
202 if (isFirstStart) {
203 if (GetAutoReverse() && GetRepeatCount() % 2 == 0) {
204 targetRotation = startTangent;
205 } else {
206 targetRotation = endTangent;
207 }
208 } else {
209 float currentRotation = target->stagingProperties_.GetRotation();
210 if (GetAutoReverse() && GetRepeatCount() % 2 == 0) {
211 targetRotation = IsReversed() ? currentRotation + byRotation : currentRotation - byRotation;
212 } else {
213 targetRotation = IsReversed() ? currentRotation - byRotation : currentRotation + byRotation;
214 }
215 }
216
217 target->stagingProperties_.SetRotation(targetRotation);
218 }
219
ReplaceSubString(std::string & sourceStr,const std::string & subStr,const std::string & newStr) const220 void RSPathAnimation::ReplaceSubString(
221 std::string& sourceStr, const std::string& subStr, const std::string& newStr) const
222 {
223 std::string::size_type position = 0;
224 while ((position = sourceStr.find(subStr)) != std::string::npos) {
225 sourceStr.replace(position, subStr.length(), newStr);
226 }
227
228 ROSEN_LOGD("SVG path:%s", sourceStr.c_str());
229 }
230
PreProcessPath(const std::string & path,const Vector2f & startValue,const Vector2f & endValue) const231 const std::shared_ptr<RSPath> RSPathAnimation::PreProcessPath(
232 const std::string& path, const Vector2f& startValue, const Vector2f& endValue) const
233 {
234 std::string animationPath = path;
235 ReplaceSubString(animationPath, "start.x", std::to_string(startValue[0]));
236 ReplaceSubString(animationPath, "start.y", std::to_string(startValue[1]));
237 ReplaceSubString(animationPath, "end.x", std::to_string(endValue[0]));
238 ReplaceSubString(animationPath, "end.y", std::to_string(endValue[1]));
239 #ifdef ROSEN_OHOS
240 return RSPath::CreateRSPath(animationPath);
241 #else
242 return nullptr;
243 #endif
244 }
245
IsAnimatablePathProperty(const RSAnimatableProperty & property)246 bool RSPathAnimation::IsAnimatablePathProperty(const RSAnimatableProperty& property)
247 {
248 if (find(PROP_FOR_PATH_ANIM.begin(), PROP_FOR_PATH_ANIM.end(), property) == PROP_FOR_PATH_ANIM.end()) {
249 return false;
250 }
251
252 return true;
253 }
254 } // namespace Rosen
255 } // namespace OHOS
256