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 {
RSPathAnimation(std::shared_ptr<RSPropertyBase> property,const std::shared_ptr<RSPath> & animationPath)31 RSPathAnimation::RSPathAnimation(std::shared_ptr<RSPropertyBase> property,
32 const std::shared_ptr<RSPath>& animationPath) : RSPropertyAnimation(property), animationPath_(animationPath)
33 {}
34
RSPathAnimation(std::shared_ptr<RSPropertyBase> property,const std::string & path,const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)35 RSPathAnimation::RSPathAnimation(std::shared_ptr<RSPropertyBase> property, const std::string& path,
36 const std::shared_ptr<RSPropertyBase>& startValue, const std::shared_ptr<RSPropertyBase>& endValue)
37 : RSPathAnimation(property, PreProcessPath(path, startValue, endValue))
38 {
39 startValue_ = startValue;
40 endValue_ = endValue;
41 InitNeedPath(startValue_, endValue_);
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 (RSAnimation::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
SetPathNeedAddOrigin(bool needAddOrigin)109 void RSPathAnimation::SetPathNeedAddOrigin(bool needAddOrigin)
110 {
111 if (IsStarted()) {
112 ROSEN_LOGE("Failed to set need Add Origin, path animation has started!");
113 return;
114 }
115
116 needAddOrigin_ = needAddOrigin;
117 }
118
GetPathNeedAddOrigin() const119 bool RSPathAnimation::GetPathNeedAddOrigin() const
120 {
121 return needAddOrigin_;
122 }
123
OnStart()124 void RSPathAnimation::OnStart()
125 {
126 if (!animationPath_) {
127 ROSEN_LOGE("Failed to start path animation, path is null!");
128 return;
129 }
130
131 RSPropertyAnimation::OnStart();
132 auto target = GetTarget().lock();
133 if (target == nullptr) {
134 ROSEN_LOGE("Failed to start curve animation, target is null!");
135 return;
136 }
137
138 InitRotationId(target);
139 auto interpolator = timingCurve_.GetInterpolator(GetDuration());
140 auto animation = std::make_shared<RSRenderPathAnimation>(GetId(), GetPropertyId(),
141 originValue_->GetRenderProperty(), startValue_->GetRenderProperty(), endValue_->GetRenderProperty(),
142 target->GetStagingProperties().GetRotation(), animationPath_);
143 UpdateParamToRenderAnimation(animation);
144 animation->SetInterpolator(interpolator);
145 animation->SetRotationMode(GetRotationMode());
146 animation->SetBeginFraction(GetBeginFraction());
147 animation->SetEndFraction(GetEndFraction());
148 animation->SetIsNeedPath(isNeedPath_);
149 animation->SetPathNeedAddOrigin(GetPathNeedAddOrigin());
150 animation->SetAdditive(GetAdditive());
151 animation->SetRotationId(rotationId_);
152 if (isNeedPath_) {
153 property_->AddPathAnimation();
154 }
155 std::unique_ptr<RSCommand> command = std::make_unique<RSAnimationCreatePath>(target->GetId(), animation);
156 auto transactionProxy = RSTransactionProxy::GetInstance();
157 if (transactionProxy != nullptr) {
158 transactionProxy->AddCommand(command, target->IsRenderServiceNode(),
159 target->GetFollowType(), target->GetId());
160 if (target->NeedForcedSendToRemote()) {
161 std::unique_ptr<RSCommand> commandForRemote =
162 std::make_unique<RSAnimationCreatePath>(target->GetId(), animation);
163 transactionProxy->AddCommand(commandForRemote, true, target->GetFollowType(), target->GetId());
164 }
165 }
166 }
167
InitInterpolationValue()168 void RSPathAnimation::InitInterpolationValue()
169 {
170 if (!animationPath_) {
171 ROSEN_LOGE("Failed to update interpolation value, path is null!");
172 return;
173 }
174
175 if (isNeedPath_) {
176 if (startValue_->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR2F &&
177 InitInterpolationVector2f(startValue_, endValue_)) {
178 return;
179 }
180 if (startValue_->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR4F &&
181 InitInterpolationVector4f(startValue_, endValue_)) {
182 return;
183 }
184 }
185
186 byValue_ = endValue_ - startValue_;
187 }
188
OnUpdateStagingValue(bool isFirstStart)189 void RSPathAnimation::OnUpdateStagingValue(bool isFirstStart)
190 {
191 auto target = GetTarget().lock();
192 if (target == nullptr) {
193 ROSEN_LOGE("Failed to update staging value, target is null!");
194 return;
195 }
196
197 RSPropertyAnimation::OnUpdateStagingValue(isFirstStart);
198
199 float startTangent = 0.0f;
200 float endTangent = 0.0f;
201 switch (rotationMode_) {
202 case RotationMode::ROTATE_NONE:
203 return;
204 case RotationMode::ROTATE_AUTO:
205 startTangent = startTangent_;
206 endTangent = endTangent_;
207 break;
208 case RotationMode::ROTATE_AUTO_REVERSE:
209 startTangent = startTangent_ + 180.0f;
210 endTangent = endTangent_ + 180.0f;
211 break;
212 default:
213 ROSEN_LOGE("Unknow rotation mode!");
214 return;
215 }
216 if (!GetDirection()) {
217 std::swap(startTangent, endTangent);
218 }
219
220 float targetRotation = 0.0f;
221 float byRotation = endTangent - startTangent;
222 if (isFirstStart) {
223 if (GetAutoReverse() && GetRepeatCount() % 2 == 0) {
224 targetRotation = startTangent;
225 } else {
226 targetRotation = endTangent;
227 }
228 } else {
229 float currentRotation = target->GetStagingProperties().GetRotation();
230 if (GetAutoReverse() && GetRepeatCount() % 2 == 0) {
231 targetRotation = IsReversed() ? currentRotation + byRotation
232 : currentRotation - byRotation;
233 } else {
234 targetRotation = IsReversed() ? currentRotation - byRotation
235 : currentRotation + byRotation;
236 }
237 }
238
239 SetRotation(target, targetRotation);
240 }
241
InitRotationId(const std::shared_ptr<RSNode> & node)242 void RSPathAnimation::InitRotationId(const std::shared_ptr<RSNode>& node)
243 {
244 if (GetRotationPropertyId(node) == 0) {
245 node->SetRotation(0.f);
246 }
247 rotationId_ = GetRotationPropertyId(node);
248 }
249
GetRotationPropertyId(const std::shared_ptr<RSNode> & node)250 PropertyId RSPathAnimation::GetRotationPropertyId(const std::shared_ptr<RSNode>& node)
251 {
252 auto iter = node->propertyModifiers_.find(RSModifierType::ROTATION);
253 if (iter != node->propertyModifiers_.end()) {
254 return iter->second->GetPropertyId();
255 }
256
257 for (const auto& [id, modifier] : node->modifiers_) {
258 if (modifier->GetModifierType() == RSModifierType::ROTATION) {
259 return modifier->GetPropertyId();
260 }
261 }
262 return 0;
263 }
264
SetRotation(const std::shared_ptr<RSNode> & node,const float rotation)265 void RSPathAnimation::SetRotation(const std::shared_ptr<RSNode>& node, const float rotation)
266 {
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:%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 auto startVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(startValue);
340 auto endVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(endValue);
341 if (startValue->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR4F &&
342 startVector4f != nullptr && endVector4f != nullptr) {
343 Vector2f start(startVector4f->Get()[0], startVector4f->Get()[1]);
344 Vector2f end(endVector4f->Get()[0], endVector4f->Get()[1]);
345 isNeedPath_ = (start != end);
346 if (isNeedPath_) {
347 SetAdditive(false);
348 }
349 return;
350 }
351
352 SetAdditive(false);
353 }
354
InitInterpolationVector2f(const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)355 bool RSPathAnimation::InitInterpolationVector2f(const std::shared_ptr<RSPropertyBase>& startValue,
356 const std::shared_ptr<RSPropertyBase>& endValue)
357 {
358 auto startVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(startValue);
359 auto endVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(endValue);
360 if (startVector2f != nullptr && endVector2f != nullptr) {
361 animationPath_->GetPosTan(0.0f * beginFraction_, startVector2f->stagingValue_, startTangent_);
362 animationPath_->GetPosTan(animationPath_->GetDistance() * endFraction_,
363 endVector2f->stagingValue_, endTangent_);
364 auto originVector2f = std::static_pointer_cast<RSProperty<Vector2f>>(GetOriginValue());
365 if (originVector2f != nullptr && needAddOrigin_) {
366 UpdateVector2fValueAddOrigin(startVector2f->stagingValue_, endVector2f->stagingValue_,
367 originVector2f->stagingValue_);
368 }
369 byValue_ = endValue - startValue;
370 return true;
371 }
372
373 return false;
374 }
375
InitInterpolationVector4f(const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)376 bool RSPathAnimation::InitInterpolationVector4f(const std::shared_ptr<RSPropertyBase>& startValue,
377 const std::shared_ptr<RSPropertyBase>& endValue)
378 {
379 auto startVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(startValue);
380 auto endVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(endValue);
381 if (startVector4f != nullptr && endVector4f != nullptr) {
382 animationPath_->GetPosTan(0.0f * beginFraction_, startVector4f->stagingValue_, startTangent_);
383 animationPath_->GetPosTan(animationPath_->GetDistance() * endFraction_,
384 endVector4f->stagingValue_, endTangent_);
385 auto originVector4f = std::static_pointer_cast<RSProperty<Vector4f>>(GetOriginValue());
386 if (originVector4f != nullptr && needAddOrigin_) {
387 UpdateVector4fValueAddOrigin(startVector4f->stagingValue_, endVector4f->stagingValue_,
388 originVector4f->stagingValue_);
389 }
390 byValue_ = endValue - startValue;
391 return true;
392 }
393
394 return false;
395 }
396
UpdateVector2fValueAddOrigin(Vector2f & startValue,Vector2f & endValue,Vector2f & deltaValue)397 void RSPathAnimation::UpdateVector2fValueAddOrigin(Vector2f& startValue, Vector2f& endValue, Vector2f& deltaValue)
398 {
399 startValue += deltaValue;
400 endValue += deltaValue;
401 }
402
UpdateVector4fValueAddOrigin(Vector4f & startValue,Vector4f & endValue,Vector4f & deltaValue)403 void RSPathAnimation::UpdateVector4fValueAddOrigin(Vector4f& startValue, Vector4f& endValue, Vector4f& deltaValue)
404 {
405 startValue[0] += deltaValue[0];
406 startValue[1] += deltaValue[1];
407 endValue[0] += deltaValue[0];
408 endValue[1] += deltaValue[1];
409 }
410 } // namespace Rosen
411 } // namespace OHOS
412