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