1 /*
2 * Copyright (c) 2021-2022 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_motion_path_option.h"
20 #include "animation/rs_render_path_animation.h"
21 #include "command/rs_animation_command.h"
22 #include "modifier/rs_modifier.h"
23 #include "modifier/rs_property.h"
24 #include "platform/common/rs_log.h"
25 #include "render/rs_path.h"
26 #include "transaction/rs_transaction_proxy.h"
27 #include "ui/rs_node.h"
28
29 namespace OHOS {
30 namespace Rosen {
31 static constexpr int NUMBER_FOR_HALF = 2;
32
RSPathAnimation(std::shared_ptr<RSPropertyBase> property,const std::shared_ptr<RSPath> & animationPath)33 RSPathAnimation::RSPathAnimation(std::shared_ptr<RSPropertyBase> property,
34 const std::shared_ptr<RSPath>& animationPath) : RSPropertyAnimation(property), animationPath_(animationPath)
35 {}
36
RSPathAnimation(std::shared_ptr<RSPropertyBase> property,const std::string & path,const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)37 RSPathAnimation::RSPathAnimation(std::shared_ptr<RSPropertyBase> property, const std::string& path,
38 const std::shared_ptr<RSPropertyBase>& startValue, const std::shared_ptr<RSPropertyBase>& endValue)
39 : RSPathAnimation(property, PreProcessPath(path, startValue, endValue))
40 {
41 startValue_ = startValue;
42 endValue_ = endValue;
43 InitNeedPath(startValue_, endValue_);
44 }
45
SetTimingCurve(const RSAnimationTimingCurve & timingCurve)46 void RSPathAnimation::SetTimingCurve(const RSAnimationTimingCurve& timingCurve)
47 {
48 timingCurve_ = timingCurve;
49 }
50
GetTimingCurve() const51 const RSAnimationTimingCurve& RSPathAnimation::GetTimingCurve() const
52 {
53 return timingCurve_;
54 }
55
SetRotationMode(const RotationMode & rotationMode)56 void RSPathAnimation::SetRotationMode(const RotationMode& rotationMode)
57 {
58 if (RSAnimation::IsStarted()) {
59 ROSEN_LOGE("Failed to enable rotate, path animation has started!");
60 return;
61 }
62
63 rotationMode_ = rotationMode;
64 }
65
GetRotationMode() const66 RotationMode RSPathAnimation::GetRotationMode() const
67 {
68 return rotationMode_;
69 }
70
SetBeginFraction(float fraction)71 void RSPathAnimation::SetBeginFraction(float fraction)
72 {
73 if (IsStarted()) {
74 ROSEN_LOGE("Failed to set begin fraction, path animation has started!");
75 return;
76 }
77
78 if (fraction < FRACTION_MIN || fraction > FRACTION_MAX || fraction > endFraction_) {
79 ROSEN_LOGE("Failed to set begin fraction, invalid value:%{public}f", fraction);
80 return;
81 }
82
83 beginFraction_ = fraction;
84 }
85
GetBeginFraction() const86 float RSPathAnimation::GetBeginFraction() const
87 {
88 return beginFraction_;
89 }
90
SetEndFraction(float fraction)91 void RSPathAnimation::SetEndFraction(float fraction)
92 {
93 if (IsStarted()) {
94 ROSEN_LOGE("Failed to set end fraction, path animation has started!");
95 return;
96 }
97
98 if (fraction < FRACTION_MIN || fraction > FRACTION_MAX || fraction < beginFraction_) {
99 ROSEN_LOGE("Failed to set end fraction, invalid value:%{public}f", fraction);
100 return;
101 }
102
103 endFraction_ = fraction;
104 }
105
GetEndFraction() const106 float RSPathAnimation::GetEndFraction() const
107 {
108 return endFraction_;
109 }
110
SetPathNeedAddOrigin(bool needAddOrigin)111 void RSPathAnimation::SetPathNeedAddOrigin(bool needAddOrigin)
112 {
113 if (IsStarted()) {
114 ROSEN_LOGE("Failed to set need Add Origin, path animation has started!");
115 return;
116 }
117
118 needAddOrigin_ = needAddOrigin;
119 }
120
GetPathNeedAddOrigin() const121 bool RSPathAnimation::GetPathNeedAddOrigin() const
122 {
123 return needAddOrigin_;
124 }
125
OnStart()126 void RSPathAnimation::OnStart()
127 {
128 if (!animationPath_) {
129 ROSEN_LOGE("Failed to start path animation, path is null!");
130 return;
131 }
132
133 RSPropertyAnimation::OnStart();
134 auto target = GetTarget().lock();
135 if (target == nullptr) {
136 ROSEN_LOGE("Failed to start curve animation, target is null!");
137 return;
138 }
139
140 InitRotationId(target);
141 auto interpolator = timingCurve_.GetInterpolator(GetDuration());
142 auto animation = std::make_shared<RSRenderPathAnimation>(GetId(), GetPropertyId(),
143 originValue_->GetRenderProperty(), startValue_->GetRenderProperty(), endValue_->GetRenderProperty(),
144 target->GetStagingProperties().GetRotation(), animationPath_);
145 UpdateParamToRenderAnimation(animation);
146 animation->SetInterpolator(interpolator);
147 animation->SetRotationMode(GetRotationMode());
148 animation->SetBeginFraction(GetBeginFraction());
149 animation->SetEndFraction(GetEndFraction());
150 animation->SetIsNeedPath(isNeedPath_);
151 animation->SetPathNeedAddOrigin(GetPathNeedAddOrigin());
152 animation->SetAdditive(GetAdditive());
153 animation->SetRotationId(rotationId_);
154 if (isNeedPath_) {
155 property_->AddPathAnimation();
156 }
157 std::unique_ptr<RSCommand> command = std::make_unique<RSAnimationCreatePath>(target->GetId(), animation);
158 auto transactionProxy = RSTransactionProxy::GetInstance();
159 if (transactionProxy != nullptr) {
160 transactionProxy->AddCommand(command, target->IsRenderServiceNode(),
161 target->GetFollowType(), target->GetId());
162 if (target->NeedForcedSendToRemote()) {
163 std::unique_ptr<RSCommand> commandForRemote =
164 std::make_unique<RSAnimationCreatePath>(target->GetId(), animation);
165 transactionProxy->AddCommand(commandForRemote, true, target->GetFollowType(), target->GetId());
166 }
167 }
168 }
169
InitInterpolationValue()170 void RSPathAnimation::InitInterpolationValue()
171 {
172 if (!animationPath_) {
173 ROSEN_LOGE("Failed to update interpolation value, path is null!");
174 return;
175 }
176
177 if (isNeedPath_) {
178 if (startValue_->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR2F &&
179 InitInterpolationVector2f(startValue_, endValue_)) {
180 return;
181 }
182 if (startValue_->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR4F &&
183 InitInterpolationVector4f(startValue_, endValue_)) {
184 return;
185 }
186 }
187
188 byValue_ = endValue_ - startValue_;
189 }
190
OnUpdateStagingValue(bool isFirstStart)191 void RSPathAnimation::OnUpdateStagingValue(bool isFirstStart)
192 {
193 auto target = GetTarget().lock();
194 if (target == nullptr) {
195 ROSEN_LOGE("Failed to update staging value, target is null!");
196 return;
197 }
198
199 RSPropertyAnimation::OnUpdateStagingValue(isFirstStart);
200
201 float startTangent = 0.0f;
202 float endTangent = 0.0f;
203 switch (rotationMode_) {
204 case RotationMode::ROTATE_NONE:
205 return;
206 case RotationMode::ROTATE_AUTO:
207 startTangent = startTangent_;
208 endTangent = endTangent_;
209 break;
210 case RotationMode::ROTATE_AUTO_REVERSE:
211 startTangent = startTangent_ + 180.0f;
212 endTangent = endTangent_ + 180.0f;
213 break;
214 default:
215 ROSEN_LOGE("Unknow rotation mode!");
216 return;
217 }
218 if (!GetDirection()) {
219 std::swap(startTangent, endTangent);
220 }
221
222 float targetRotation = 0.0f;
223 if (isFirstStart) {
224 if (GetAutoReverse() && GetRepeatCount() % NUMBER_FOR_HALF == 0) {
225 targetRotation = startTangent;
226 } else {
227 targetRotation = endTangent;
228 }
229 } else {
230 float byRotation = endTangent - startTangent;
231 float currentRotation = target->GetStagingProperties().GetRotation();
232 if (GetAutoReverse() && GetRepeatCount() % NUMBER_FOR_HALF == 0) {
233 targetRotation = IsReversed() ? currentRotation + byRotation
234 : currentRotation - byRotation;
235 } else {
236 targetRotation = IsReversed() ? currentRotation - byRotation
237 : currentRotation + byRotation;
238 }
239 }
240
241 SetRotation(target, targetRotation);
242 }
243
InitRotationId(const std::shared_ptr<RSNode> & node)244 void RSPathAnimation::InitRotationId(const std::shared_ptr<RSNode>& node)
245 {
246 if (GetRotationPropertyId(node) == 0) {
247 node->SetRotation(0.f);
248 }
249 rotationId_ = GetRotationPropertyId(node);
250 }
251
GetRotationPropertyId(const std::shared_ptr<RSNode> & node)252 PropertyId RSPathAnimation::GetRotationPropertyId(const std::shared_ptr<RSNode>& node)
253 {
254 std::unique_lock<std::recursive_mutex> lock(node->GetPropertyMutex());
255 auto iter = node->propertyModifiers_.find(RSModifierType::ROTATION);
256 if (iter != node->propertyModifiers_.end()) {
257 return iter->second->GetPropertyId();
258 }
259
260 for (const auto& [id, modifier] : node->modifiers_) {
261 if (modifier->GetModifierType() == RSModifierType::ROTATION) {
262 return modifier->GetPropertyId();
263 }
264 }
265 return 0;
266 }
267
SetRotation(const std::shared_ptr<RSNode> & node,const float rotation)268 void RSPathAnimation::SetRotation(const std::shared_ptr<RSNode>& node, const float rotation)
269 {
270 std::unique_lock<std::recursive_mutex> lock(node->GetPropertyMutex());
271 auto iter = node->modifiers_.find(rotationId_);
272 if (iter != node->modifiers_.end()) {
273 auto modifier = iter->second;
274 if (modifier != nullptr) {
275 std::static_pointer_cast<RSProperty<float>>(modifier->GetProperty())->stagingValue_ = rotation;
276 }
277 return;
278 }
279
280 for (const auto& [type, modifier] : node->propertyModifiers_) {
281 if (modifier != nullptr && modifier->GetPropertyId() == rotationId_) {
282 std::static_pointer_cast<RSProperty<float>>(modifier->GetProperty())->stagingValue_ = rotation;
283 }
284 return;
285 }
286 }
287
OnCallFinishCallback()288 void RSPathAnimation::OnCallFinishCallback()
289 {
290 if (property_ != nullptr) {
291 property_->RemovePathAnimation();
292 }
293 }
294
ReplaceSubString(std::string & sourceStr,const std::string & subStr,const std::string & newStr) const295 void RSPathAnimation::ReplaceSubString(std::string& sourceStr, const std::string& subStr,
296 const std::string& newStr) const
297 {
298 std::string::size_type position = 0;
299 while ((position = sourceStr.find(subStr)) != std::string::npos) {
300 sourceStr.replace(position, subStr.length(), newStr);
301 }
302
303 ROSEN_LOGD("SVG path:%{public}s", sourceStr.c_str());
304 }
305
ProcessPath(const std::string & path,const float startX,const float startY,const float endX,const float endY) const306 const std::shared_ptr<RSPath> RSPathAnimation::ProcessPath(const std::string& path, const float startX,
307 const float startY, const float endX, const float endY) const
308 {
309 std::string animationPath = path;
310 ReplaceSubString(animationPath, "start.x", std::to_string(startX));
311 ReplaceSubString(animationPath, "start.y", std::to_string(startY));
312 ReplaceSubString(animationPath, "end.x", std::to_string(endX));
313 ReplaceSubString(animationPath, "end.y", std::to_string(endY));
314 return RSPath::CreateRSPath(animationPath);
315 }
316
PreProcessPath(const std::string & path,const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue) const317 const std::shared_ptr<RSPath> RSPathAnimation::PreProcessPath(const std::string& path,
318 const std::shared_ptr<RSPropertyBase>& startValue,
319 const std::shared_ptr<RSPropertyBase>& endValue) const
320 {
321 auto startVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(startValue);
322 auto endVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(endValue);
323 if (startValue->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR2F && startVector2f != nullptr &&
324 endVector2f != nullptr) {
325 return ProcessPath(path, startVector2f->Get()[0], startVector2f->Get()[1], endVector2f->Get()[0],
326 endVector2f->Get()[1]);
327 }
328
329 auto startVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(startValue);
330 auto endVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(endValue);
331 if (startValue->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR4F && startVector4f != nullptr &&
332 endVector4f != nullptr) {
333 return ProcessPath(path, startVector4f->Get()[0], startVector4f->Get()[1], endVector4f->Get()[0],
334 endVector4f->Get()[1]);
335 }
336
337 return {};
338 }
339
InitNeedPath(const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)340 void RSPathAnimation::InitNeedPath(const std::shared_ptr<RSPropertyBase>& startValue,
341 const std::shared_ptr<RSPropertyBase>& endValue)
342 {
343 if (startValue == nullptr || endValue == nullptr) {
344 ROSEN_LOGD("Input is invaild, failed to InitNeedPath.");
345 return;
346 }
347 auto startVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(startValue);
348 auto endVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(endValue);
349 if (startValue->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR4F &&
350 startVector4f != nullptr && endVector4f != nullptr) {
351 Vector2f start(startVector4f->Get()[0], startVector4f->Get()[1]);
352 Vector2f end(endVector4f->Get()[0], endVector4f->Get()[1]);
353 isNeedPath_ = (start != end);
354 if (isNeedPath_) {
355 SetAdditive(false);
356 }
357 return;
358 }
359
360 SetAdditive(false);
361 }
362
InitInterpolationVector2f(const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)363 bool RSPathAnimation::InitInterpolationVector2f(const std::shared_ptr<RSPropertyBase>& startValue,
364 const std::shared_ptr<RSPropertyBase>& endValue)
365 {
366 auto startVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(startValue);
367 auto endVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(endValue);
368 if (startVector2f != nullptr && endVector2f != nullptr) {
369 animationPath_->GetPosTan(0.0f * beginFraction_, startVector2f->stagingValue_, startTangent_);
370 animationPath_->GetPosTan(animationPath_->GetDistance() * endFraction_,
371 endVector2f->stagingValue_, endTangent_);
372 auto originVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(GetOriginValue());
373 if (originVector2f != nullptr && needAddOrigin_) {
374 UpdateVector2fValueAddOrigin(startVector2f->stagingValue_, endVector2f->stagingValue_,
375 originVector2f->stagingValue_);
376 }
377 byValue_ = endValue - startValue;
378 return true;
379 }
380
381 return false;
382 }
383
InitInterpolationVector4f(const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)384 bool RSPathAnimation::InitInterpolationVector4f(const std::shared_ptr<RSPropertyBase>& startValue,
385 const std::shared_ptr<RSPropertyBase>& endValue)
386 {
387 auto startVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(startValue);
388 auto endVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(endValue);
389 if (startVector4f != nullptr && endVector4f != nullptr) {
390 animationPath_->GetPosTan(0.0f * beginFraction_, startVector4f->stagingValue_, startTangent_);
391 animationPath_->GetPosTan(animationPath_->GetDistance() * endFraction_,
392 endVector4f->stagingValue_, endTangent_);
393 auto originVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(GetOriginValue());
394 if (originVector4f != nullptr && needAddOrigin_) {
395 UpdateVector4fValueAddOrigin(startVector4f->stagingValue_, endVector4f->stagingValue_,
396 originVector4f->stagingValue_);
397 }
398 byValue_ = endValue - startValue;
399 return true;
400 }
401
402 return false;
403 }
404
UpdateVector2fValueAddOrigin(Vector2f & startValue,Vector2f & endValue,Vector2f & deltaValue)405 void RSPathAnimation::UpdateVector2fValueAddOrigin(Vector2f& startValue, Vector2f& endValue, Vector2f& deltaValue)
406 {
407 startValue += deltaValue;
408 endValue += deltaValue;
409 }
410
UpdateVector4fValueAddOrigin(Vector4f & startValue,Vector4f & endValue,Vector4f & deltaValue)411 void RSPathAnimation::UpdateVector4fValueAddOrigin(Vector4f& startValue, Vector4f& endValue, Vector4f& deltaValue)
412 {
413 startValue[0] += deltaValue[0];
414 startValue[1] += deltaValue[1];
415 endValue[0] += deltaValue[0];
416 endValue[1] += deltaValue[1];
417 }
418 } // namespace Rosen
419 } // namespace OHOS
420