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 path curve animation, target is null!");
137         return;
138     }
139     auto transactionProxy = RSTransactionProxy::GetInstance();
140     if (transactionProxy == nullptr) {
141         ROSEN_LOGE("Failed to start path animation, transaction proxy is null!");
142         return;
143     }
144 
145     InitRotationId(target);
146     auto interpolator = timingCurve_.GetInterpolator(GetDuration());
147     auto animation = std::make_shared<RSRenderPathAnimation>(GetId(), GetPropertyId(),
148         originValue_->GetRenderProperty(), startValue_->GetRenderProperty(), endValue_->GetRenderProperty(),
149         target->GetStagingProperties().GetRotation(), animationPath_);
150     UpdateParamToRenderAnimation(animation);
151     animation->SetInterpolator(interpolator);
152     animation->SetRotationMode(GetRotationMode());
153     animation->SetBeginFraction(GetBeginFraction());
154     animation->SetEndFraction(GetEndFraction());
155     animation->SetIsNeedPath(isNeedPath_);
156     animation->SetPathNeedAddOrigin(GetPathNeedAddOrigin());
157     animation->SetAdditive(GetAdditive());
158     animation->SetRotationId(rotationId_);
159     if (isNeedPath_) {
160         property_->AddPathAnimation();
161     }
162     std::unique_ptr<RSCommand> command = std::make_unique<RSAnimationCreatePath>(target->GetId(), animation);
163     transactionProxy->AddCommand(command, target->IsRenderServiceNode(), target->GetFollowType(), target->GetId());
164     if (target->NeedForcedSendToRemote()) {
165         std::unique_ptr<RSCommand> commandForRemote =
166             std::make_unique<RSAnimationCreatePath>(target->GetId(), animation);
167         transactionProxy->AddCommand(commandForRemote, true, target->GetFollowType(), target->GetId());
168     }
169 }
170 
InitInterpolationValue()171 void RSPathAnimation::InitInterpolationValue()
172 {
173     if (!animationPath_) {
174         ROSEN_LOGE("Failed to update interpolation value, path is null!");
175         return;
176     }
177 
178     if (isNeedPath_) {
179         if (startValue_->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR2F &&
180             InitInterpolationVector2f(startValue_, endValue_)) {
181             return;
182         }
183         if (startValue_->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR4F &&
184             InitInterpolationVector4f(startValue_, endValue_)) {
185             return;
186         }
187     }
188 
189     byValue_ = endValue_ - startValue_;
190 }
191 
OnUpdateStagingValue(bool isFirstStart)192 void RSPathAnimation::OnUpdateStagingValue(bool isFirstStart)
193 {
194     auto target = GetTarget().lock();
195     if (target == nullptr) {
196         ROSEN_LOGE("Failed to update staging value, target is null!");
197         return;
198     }
199 
200     RSPropertyAnimation::OnUpdateStagingValue(isFirstStart);
201 
202     float startTangent = 0.0f;
203     float endTangent = 0.0f;
204     switch (rotationMode_) {
205         case RotationMode::ROTATE_NONE:
206             return;
207         case RotationMode::ROTATE_AUTO:
208             startTangent = startTangent_;
209             endTangent = endTangent_;
210             break;
211         case RotationMode::ROTATE_AUTO_REVERSE:
212             startTangent = startTangent_ + 180.0f;
213             endTangent = endTangent_ + 180.0f;
214             break;
215         default:
216             ROSEN_LOGE("Unknow rotation mode!");
217             return;
218     }
219     if (!GetDirection()) {
220         std::swap(startTangent, endTangent);
221     }
222 
223     float targetRotation = 0.0f;
224     if (isFirstStart) {
225         if (GetAutoReverse() && GetRepeatCount() % NUMBER_FOR_HALF == 0) {
226             targetRotation = startTangent;
227         } else {
228             targetRotation = endTangent;
229         }
230     } else {
231         float byRotation = endTangent - startTangent;
232         float currentRotation = target->GetStagingProperties().GetRotation();
233         if (GetAutoReverse() && GetRepeatCount() % NUMBER_FOR_HALF == 0) {
234             targetRotation = IsReversed() ? currentRotation + byRotation
235                 : currentRotation - byRotation;
236         } else {
237             targetRotation = IsReversed() ? currentRotation - byRotation
238                 : currentRotation + byRotation;
239         }
240     }
241 
242     SetRotation(target, targetRotation);
243 }
244 
InitRotationId(const std::shared_ptr<RSNode> & node)245 void RSPathAnimation::InitRotationId(const std::shared_ptr<RSNode>& node)
246 {
247     if (GetRotationPropertyId(node) == 0) {
248         node->SetRotation(0.f);
249     }
250     rotationId_ = GetRotationPropertyId(node);
251 }
252 
GetRotationPropertyId(const std::shared_ptr<RSNode> & node)253 PropertyId RSPathAnimation::GetRotationPropertyId(const std::shared_ptr<RSNode>& node)
254 {
255     std::unique_lock<std::recursive_mutex> lock(node->GetPropertyMutex());
256     auto iter = node->propertyModifiers_.find(RSModifierType::ROTATION);
257     if (iter != node->propertyModifiers_.end()) {
258         return iter->second->GetPropertyId();
259     }
260 
261     for (const auto& [id, modifier] : node->modifiers_) {
262         if (modifier->GetModifierType() == RSModifierType::ROTATION) {
263             return modifier->GetPropertyId();
264         }
265     }
266     return 0;
267 }
268 
SetRotation(const std::shared_ptr<RSNode> & node,const float rotation)269 void RSPathAnimation::SetRotation(const std::shared_ptr<RSNode>& node, const float rotation)
270 {
271     std::unique_lock<std::recursive_mutex> lock(node->GetPropertyMutex());
272     auto iter = node->modifiers_.find(rotationId_);
273     if (iter != node->modifiers_.end()) {
274         auto modifier = iter->second;
275         if (modifier != nullptr) {
276             std::static_pointer_cast<RSProperty<float>>(modifier->GetProperty())->stagingValue_ = rotation;
277         }
278         return;
279     }
280 
281     for (const auto& [type, modifier] : node->propertyModifiers_) {
282         if (modifier != nullptr && modifier->GetPropertyId() == rotationId_) {
283             std::static_pointer_cast<RSProperty<float>>(modifier->GetProperty())->stagingValue_ = rotation;
284         }
285         return;
286     }
287 }
288 
OnCallFinishCallback()289 void RSPathAnimation::OnCallFinishCallback()
290 {
291     if (property_ != nullptr) {
292         property_->RemovePathAnimation();
293     }
294 }
295 
ReplaceSubString(std::string & sourceStr,const std::string & subStr,const std::string & newStr) const296 void RSPathAnimation::ReplaceSubString(std::string& sourceStr, const std::string& subStr,
297     const std::string& newStr) const
298 {
299     std::string::size_type position = 0;
300     while ((position = sourceStr.find(subStr)) != std::string::npos) {
301         sourceStr.replace(position, subStr.length(), newStr);
302     }
303 
304     ROSEN_LOGD("SVG path:%{public}s", sourceStr.c_str());
305 }
306 
ProcessPath(const std::string & path,const float startX,const float startY,const float endX,const float endY) const307 const std::shared_ptr<RSPath> RSPathAnimation::ProcessPath(const std::string& path, const float startX,
308     const float startY, const float endX, const float endY) const
309 {
310     std::string animationPath = path;
311     ReplaceSubString(animationPath, "start.x", std::to_string(startX));
312     ReplaceSubString(animationPath, "start.y", std::to_string(startY));
313     ReplaceSubString(animationPath, "end.x", std::to_string(endX));
314     ReplaceSubString(animationPath, "end.y", std::to_string(endY));
315     return RSPath::CreateRSPath(animationPath);
316 }
317 
PreProcessPath(const std::string & path,const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue) const318 const std::shared_ptr<RSPath> RSPathAnimation::PreProcessPath(const std::string& path,
319     const std::shared_ptr<RSPropertyBase>& startValue,
320     const std::shared_ptr<RSPropertyBase>& endValue) const
321 {
322     auto startVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(startValue);
323     auto endVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(endValue);
324     if (startValue->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR2F && startVector2f != nullptr &&
325         endVector2f != nullptr) {
326         return ProcessPath(path, startVector2f->Get()[0], startVector2f->Get()[1], endVector2f->Get()[0],
327             endVector2f->Get()[1]);
328     }
329 
330     auto startVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(startValue);
331     auto endVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(endValue);
332     if (startValue->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR4F && startVector4f != nullptr &&
333         endVector4f != nullptr) {
334         return ProcessPath(path, startVector4f->Get()[0], startVector4f->Get()[1], endVector4f->Get()[0],
335             endVector4f->Get()[1]);
336     }
337 
338     return {};
339 }
340 
InitNeedPath(const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)341 void RSPathAnimation::InitNeedPath(const std::shared_ptr<RSPropertyBase>& startValue,
342     const std::shared_ptr<RSPropertyBase>& endValue)
343 {
344     if (startValue == nullptr || endValue == nullptr) {
345         ROSEN_LOGD("Input is invaild, failed to InitNeedPath.");
346         return;
347     }
348     auto startVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(startValue);
349     auto endVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(endValue);
350     if (startValue->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR4F &&
351         startVector4f != nullptr && endVector4f != nullptr) {
352         Vector2f start(startVector4f->Get()[0], startVector4f->Get()[1]);
353         Vector2f end(endVector4f->Get()[0], endVector4f->Get()[1]);
354         isNeedPath_ = (start != end);
355         if (isNeedPath_) {
356             SetAdditive(false);
357         }
358         return;
359     }
360 
361     SetAdditive(false);
362 }
363 
InitInterpolationVector2f(const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)364 bool RSPathAnimation::InitInterpolationVector2f(const std::shared_ptr<RSPropertyBase>& startValue,
365     const std::shared_ptr<RSPropertyBase>& endValue)
366 {
367     auto startVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(startValue);
368     auto endVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(endValue);
369     if (startVector2f != nullptr && endVector2f != nullptr) {
370         animationPath_->GetPosTan(0.0f * beginFraction_, startVector2f->stagingValue_, startTangent_);
371         animationPath_->GetPosTan(animationPath_->GetDistance() * endFraction_,
372             endVector2f->stagingValue_, endTangent_);
373         auto originVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(GetOriginValue());
374         if (originVector2f != nullptr && needAddOrigin_) {
375             UpdateVector2fValueAddOrigin(startVector2f->stagingValue_, endVector2f->stagingValue_,
376                 originVector2f->stagingValue_);
377         }
378         byValue_ = endValue - startValue;
379         return true;
380     }
381 
382     return false;
383 }
384 
InitInterpolationVector4f(const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)385 bool RSPathAnimation::InitInterpolationVector4f(const std::shared_ptr<RSPropertyBase>& startValue,
386     const std::shared_ptr<RSPropertyBase>& endValue)
387 {
388     auto startVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(startValue);
389     auto endVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(endValue);
390     if (startVector4f != nullptr && endVector4f != nullptr) {
391         animationPath_->GetPosTan(0.0f * beginFraction_, startVector4f->stagingValue_, startTangent_);
392         animationPath_->GetPosTan(animationPath_->GetDistance() * endFraction_,
393             endVector4f->stagingValue_, endTangent_);
394         auto originVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(GetOriginValue());
395         if (originVector4f != nullptr && needAddOrigin_) {
396             UpdateVector4fValueAddOrigin(startVector4f->stagingValue_, endVector4f->stagingValue_,
397                 originVector4f->stagingValue_);
398         }
399         byValue_ = endValue - startValue;
400         return true;
401     }
402 
403     return false;
404 }
405 
UpdateVector2fValueAddOrigin(Vector2f & startValue,Vector2f & endValue,Vector2f & deltaValue)406 void RSPathAnimation::UpdateVector2fValueAddOrigin(Vector2f& startValue, Vector2f& endValue, Vector2f& deltaValue)
407 {
408     startValue += deltaValue;
409     endValue += deltaValue;
410 }
411 
UpdateVector4fValueAddOrigin(Vector4f & startValue,Vector4f & endValue,Vector4f & deltaValue)412 void RSPathAnimation::UpdateVector4fValueAddOrigin(Vector4f& startValue, Vector4f& endValue, Vector4f& deltaValue)
413 {
414     startValue[0] += deltaValue[0];
415     startValue[1] += deltaValue[1];
416     endValue[0] += deltaValue[0];
417     endValue[1] += deltaValue[1];
418 }
419 } // namespace Rosen
420 } // namespace OHOS
421