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