1 /*
2 * Copyright (c) 2023-2024 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 <cmath>
17
18 #include "animation/rs_keyframe_animation.h"
19 #include "animation/rs_symbol_animation.h"
20 #include "draw/paint.h"
21 #include "modifier_ng/appearance/rs_alpha_modifier.h"
22 #include "modifier_ng/appearance/rs_foreground_filter_modifier.h"
23 #include "modifier_ng/geometry/rs_bounds_modifier.h"
24 #include "modifier_ng/geometry/rs_frame_modifier.h"
25 #include "modifier_ng/geometry/rs_transform_modifier.h"
26 #include "platform/common/rs_log.h"
27 #include "rs_trace.h"
28 #include "skia_txt/default_symbol_config.h"
29 #include "utils/point.h"
30
31 namespace OHOS {
32 namespace Rosen {
33 using SymnolBaseFunc = std::function<void(const Drawing::DrawingPiecewiseParameter& parameter)>;
34 using SymbolBaseFuncMap = std::unordered_map<std::string, SymnolBaseFunc>;
35
36 static const Vector2f CENTER_NODE_COORDINATE = { 0.5f, 0.5f }; // scale center node
37 static const std::string SCALE_PROP_X = "sx";
38 static const std::string SCALE_PROP_Y = "sy";
39 static const std::string ALPHA_PROP = "alpha";
40 static const std::string BLUR_PROP = "blur";
41 static const std::string TRANSLATE_PROP_X = "tx";
42 static const std::string TRANSLATE_PROP_Y = "ty";
43 static const std::string TRANSLATE_RATIO = "tr";
44 static const std::string CLIP_PROP = "clip";
45 static const size_t PROPERTIES = 2; // symbol animation property contains two values, change from one to the other
46 static const unsigned int PROP_START = 0; // symbol animation property contains two values, change from START to the END
47 static const unsigned int PROP_END = 1; // symbol animation property contains two values, change from START to the END
48 static const unsigned int NODE_WIDTH = 2;
49 static const unsigned int NODE_HEIGHT = 3;
50 static const unsigned int INVALID_STATUS = 0; // invalid status label
51 static const unsigned int APPEAR_STATUS = 1 ; // appear status label
52 static const float EXPANSION_RATIO = 0.1f; // the proportion than needs to be expanded
53
54 namespace SymbolAnimation {
55 template<typename T>
CreateOrSetModifierValue(std::shared_ptr<RSAnimatableProperty<T>> & property,const T & value)56 bool CreateOrSetModifierValue(std::shared_ptr<RSAnimatableProperty<T>>& property, const T& value)
57 {
58 if (property == nullptr) {
59 property = std::make_shared<RSAnimatableProperty<T>>(value);
60 return true;
61 }
62 property->Set(value);
63 return false;
64 }
65
66 template<typename T>
ElementInMap(const std::string & curElement,const std::map<std::string,T> & curMap)67 bool ElementInMap(const std::string& curElement, const std::map<std::string, T>& curMap)
68 {
69 auto element = curMap.find(curElement);
70 return (element != curMap.end());
71 }
72
CurveArgsInMap(const std::string & curElement,const std::map<std::string,float> & curMap)73 float CurveArgsInMap(const std::string& curElement, const std::map<std::string, float>& curMap)
74 {
75 auto element = curMap.find(curElement);
76 if (element == curMap.end()) {
77 return 0.0f;
78 }
79 return element->second;
80 }
81
CreateAnimationTimingCurve(const OHOS::Rosen::Drawing::DrawingCurveType type,const std::map<std::string,float> & curveArgs,RSAnimationTimingCurve & curve)82 void CreateAnimationTimingCurve(const OHOS::Rosen::Drawing::DrawingCurveType type,
83 const std::map<std::string, float>& curveArgs, RSAnimationTimingCurve& curve)
84 {
85 curve = RSAnimationTimingCurve();
86 if (type == OHOS::Rosen::Drawing::DrawingCurveType::LINEAR) {
87 curve = RSAnimationTimingCurve::LINEAR;
88 } else if (type == OHOS::Rosen::Drawing::DrawingCurveType::SPRING) {
89 float scaleVelocity = CurveArgsInMap("velocity", curveArgs);
90 float scaleMass = CurveArgsInMap("mass", curveArgs);
91 float scaleStiffness = CurveArgsInMap("stiffness", curveArgs);
92 float scaleDamping = CurveArgsInMap("damping", curveArgs);
93 curve = RSAnimationTimingCurve::CreateInterpolatingSpring(scaleMass, scaleStiffness, scaleDamping,
94 scaleVelocity);
95 } else if (type == OHOS::Rosen::Drawing::DrawingCurveType::FRICTION ||
96 type == OHOS::Rosen::Drawing::DrawingCurveType::SHARP) {
97 float ctrlX1 = CurveArgsInMap("ctrlX1", curveArgs);
98 float ctrlY1 = CurveArgsInMap("ctrlY1", curveArgs);
99 float ctrlX2 = CurveArgsInMap("ctrlX2", curveArgs);
100 float ctrlY2 = CurveArgsInMap("ctrlY2", curveArgs);
101 curve = RSAnimationTimingCurve::CreateCubicCurve(ctrlX1, ctrlY1, ctrlX2, ctrlY2);
102 }
103 }
104
CalcOneTimePercent(std::vector<float> & timePercents,const uint32_t totalDuration,const uint32_t duration)105 void CalcOneTimePercent(std::vector<float>& timePercents, const uint32_t totalDuration, const uint32_t duration)
106 {
107 if (totalDuration == 0) {
108 return;
109 }
110 float timePercent = static_cast<float>(duration) / static_cast<float>(totalDuration);
111 timePercent = timePercent > 1 ? 1.0 : timePercent;
112 timePercents.push_back(timePercent);
113 }
114 } // namespace SymbolAnimation
115
RSSymbolAnimation()116 RSSymbolAnimation::RSSymbolAnimation() {}
117
~RSSymbolAnimation()118 RSSymbolAnimation::~RSSymbolAnimation() {}
119
120 /**
121 * @brief SymbolAnimation interface for arkui
122 * @param symbolAnimationConfig indicates all the information about a symbol
123 * @return true if set animation success
124 */
SetSymbolAnimation(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig)125 bool RSSymbolAnimation::SetSymbolAnimation(
126 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig)
127 {
128 RS_TRACE_FUNC();
129 if (rsNode_ == nullptr || symbolAnimationConfig == nullptr) {
130 ROSEN_LOGD("HmSymbol RSSymbolAnimation::getNode or get symbolAnimationConfig:failed");
131 return false;
132 }
133
134 if (symbolAnimationConfig->effectStrategy == Drawing::DrawingEffectStrategy::NONE) {
135 std::lock_guard<std::mutex> lock(rsNode_->childrenNodeLock_);
136 rsNode_->replaceNodesSwapArr_[INVALID_STATUS].clear();
137 rsNode_->replaceNodesSwapArr_[APPEAR_STATUS].clear();
138 rsNode_->canvasNodesListMap_.erase(symbolAnimationConfig->symbolSpanId);
139 return true; // pre code already clear nodes.
140 }
141
142 if (!symbolAnimationConfig->currentAnimationHasPlayed) {
143 switch (symbolAnimationConfig->effectStrategy) {
144 case Drawing::DrawingEffectStrategy::REPLACE_APPEAR:
145 case Drawing::DrawingEffectStrategy::QUICK_REPLACE_APPEAR:
146 PopNodeFromReplaceList(symbolAnimationConfig->symbolSpanId);
147 break;
148 case Drawing::DrawingEffectStrategy::TEXT_FLIP:
149 PopNodeFromFlipList(symbolAnimationConfig->symbolSpanId);
150 break;
151 default:
152 NodeProcessBeforeAnimation(symbolAnimationConfig);
153 break;
154 }
155 }
156
157 InitSupportAnimationTable(symbolAnimationConfig);
158
159 switch (symbolAnimationConfig->effectStrategy) {
160 case Drawing::DrawingEffectStrategy::REPLACE_APPEAR:
161 case Drawing::DrawingEffectStrategy::QUICK_REPLACE_APPEAR:
162 return SetReplaceAnimation(symbolAnimationConfig);
163 case Drawing::DrawingEffectStrategy::TEXT_FLIP:
164 return SetTextFlipAnimation(symbolAnimationConfig);
165 case Drawing::DrawingEffectStrategy::DISABLE:
166 return SetDisableAnimation(symbolAnimationConfig);
167 default:
168 return SetPublicAnimation(symbolAnimationConfig);
169 }
170 }
171
NodeProcessBeforeAnimation(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig)172 void RSSymbolAnimation::NodeProcessBeforeAnimation(
173 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig)
174 {
175 std::lock_guard<std::mutex> lock(rsNode_->childrenNodeLock_);
176 rsNode_->canvasNodesListMap_.erase(symbolAnimationConfig->symbolSpanId);
177 }
178
PopNodeFromReplaceList(uint64_t symbolSpanId)179 void RSSymbolAnimation::PopNodeFromReplaceList(uint64_t symbolSpanId)
180 {
181 PopNodeFromReplaceList(symbolSpanId, rsNode_);
182 std::lock_guard<std::mutex> lock(rsNode_->childrenNodeLock_);
183 if (rsNode_->canvasNodesListMap_[symbolSpanId].find(symbolSpanId) !=
184 rsNode_->canvasNodesListMap_[symbolSpanId].end()) {
185 PopNodeFromReplaceList(symbolSpanId, rsNode_->canvasNodesListMap_[symbolSpanId][symbolSpanId]);
186 }
187 }
188
PopNodeFromReplaceList(uint64_t symbolSpanId,const std::shared_ptr<RSNode> & rsNode)189 void RSSymbolAnimation::PopNodeFromReplaceList(uint64_t symbolSpanId,
190 const std::shared_ptr<RSNode>& rsNode)
191 {
192 std::lock_guard<std::mutex> lock(rsNode->childrenNodeLock_);
193 if (rsNode->canvasNodesListMap_.count(symbolSpanId) == 0) {
194 rsNode->canvasNodesListMap_[symbolSpanId] = {};
195 }
196
197 for (const auto& config : rsNode->replaceNodesSwapArr_[INVALID_STATUS]) {
198 rsNode->canvasNodesListMap_[symbolSpanId].erase(config.nodeId);
199 }
200 rsNode->replaceNodesSwapArr_[INVALID_STATUS].clear();
201 }
202
PopNodeFromFlipList(uint64_t symbolSpanId)203 void RSSymbolAnimation::PopNodeFromFlipList(uint64_t symbolSpanId)
204 {
205 std::lock_guard<std::mutex> lock(rsNode_->childrenNodeLock_);
206 auto it = rsNode_->canvasNodesListMap_.find(symbolSpanId);
207 if (it == rsNode_->canvasNodesListMap_.end()) {
208 it = rsNode_->canvasNodesListMap_.insert({symbolSpanId,
209 std::unordered_map<NodeId, std::shared_ptr<RSNode>>()}).first;
210 }
211 it->second.erase(INVALID_STATUS);
212 }
213
214 /**
215 * @brief Set Disappear config of replace animation
216 * @param symbolAnimationConfig is the symbol animation config of new symbol
217 * @param disappearConfig set the symbol animation config of old symbol
218 */
SetDisappearConfig(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig,std::shared_ptr<TextEngine::SymbolAnimationConfig> & disappearConfig,const std::shared_ptr<RSNode> & rsNode)219 bool RSSymbolAnimation::SetDisappearConfig(
220 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig,
221 std::shared_ptr<TextEngine::SymbolAnimationConfig>& disappearConfig,
222 const std::shared_ptr<RSNode>& rsNode)
223 {
224 if (symbolAnimationConfig == nullptr || disappearConfig == nullptr) {
225 ROSEN_LOGD("[%{public}s]: symbolAnimationConfig or disappearConfig is nullptr", __func__);
226 return false;
227 }
228
229 disappearConfig->repeatCount = symbolAnimationConfig->repeatCount;
230 disappearConfig->animationMode = symbolAnimationConfig->animationMode;
231 disappearConfig->animationStart = symbolAnimationConfig->animationStart;
232 disappearConfig->symbolSpanId = symbolAnimationConfig->symbolSpanId;
233 disappearConfig->commonSubType = symbolAnimationConfig->commonSubType;
234 disappearConfig->effectStrategy = symbolAnimationConfig->effectStrategy;
235
236 // count node levels and animation levels
237 uint32_t numNodes = 0;
238 int animationLevelNum = -1; // -1 is initial value, that is no animation levels
239 const auto& disappearNodes = rsNode->replaceNodesSwapArr_[APPEAR_STATUS];
240 for (const auto& config : disappearNodes) {
241 TextEngine::SymbolNode symbolNode;
242 symbolNode.animationIndex = config.symbolNode.animationIndex;
243 disappearConfig->symbolNodes.push_back(symbolNode);
244 animationLevelNum =
245 animationLevelNum < symbolNode.animationIndex ? symbolNode.animationIndex : animationLevelNum;
246 numNodes++;
247 }
248 disappearConfig->numNodes = numNodes;
249 // 0 is the byLayer effect and 1 is the wholeSymbol effect
250 disappearConfig->animationMode = animationLevelNum > 0 ? 0 : 1;
251 return numNodes > 0;
252 }
253
SetReplaceAnimation(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig)254 bool RSSymbolAnimation::SetReplaceAnimation(
255 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig)
256 {
257 std::shared_ptr<RSNode> rsNode = nullptr;
258 CreateSameNode(symbolAnimationConfig->symbolSpanId, rsNode, rsNode_);
259 if (rsNode == nullptr) {
260 ROSEN_LOGE("Failed to create rsNode");
261 return false;
262 }
263 // if there is mask layer, set the blendmode on the original node rsNode_
264 if (isMaskSymbol_) {
265 rsNode_->SetColorBlendMode(RSColorBlendMode::SRC_OVER);
266 rsNode_->SetColorBlendApplyType(RSColorBlendApplyType::SAVE_LAYER_ALPHA);
267 }
268 // set shadow
269 if (symbolAnimationConfig->symbolShadow.has_value()) {
270 auto symbolShadow = symbolAnimationConfig->symbolShadow.value();
271 SetSymbolShadow(symbolShadow, rsNode);
272 }
273
274 if (!symbolAnimationConfig->currentAnimationHasPlayed) {
275 auto disappearConfig = std::make_shared<TextEngine::SymbolAnimationConfig>();
276 if (SetDisappearConfig(symbolAnimationConfig, disappearConfig, rsNode)) {
277 SetReplaceDisappear(disappearConfig, rsNode);
278 }
279 }
280 SetReplaceAppear(symbolAnimationConfig, rsNode,
281 !rsNode->replaceNodesSwapArr_[INVALID_STATUS].empty());
282 return true;
283 }
284
SetReplaceDisappear(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig,const std::shared_ptr<RSNode> & rsNode)285 bool RSSymbolAnimation::SetReplaceDisappear(
286 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig,
287 const std::shared_ptr<RSNode>& rsNode)
288 {
289 if (symbolAnimationConfig->numNodes == 0) {
290 ROSEN_LOGD("[%{public}s] numNodes in symbolAnimationConfig is 0", __func__);
291 return false;
292 }
293
294 auto& disappearNodes = rsNode->replaceNodesSwapArr_[APPEAR_STATUS];
295 std::vector<std::vector<Drawing::DrawingPiecewiseParameter>> parameters;
296 Drawing::DrawingEffectStrategy effectStrategy;
297 if (symbolAnimationConfig->effectStrategy == Drawing::DrawingEffectStrategy::REPLACE_APPEAR) {
298 effectStrategy = Drawing::DrawingEffectStrategy::REPLACE_DISAPPEAR;
299 } else if (symbolAnimationConfig->effectStrategy == Drawing::DrawingEffectStrategy::QUICK_REPLACE_APPEAR) {
300 effectStrategy = Drawing::DrawingEffectStrategy::QUICK_REPLACE_DISAPPEAR;
301 }
302
303 bool res = GetAnimationGroupParameters(symbolAnimationConfig, parameters, effectStrategy);
304 for (const auto& config : disappearNodes) {
305 if (!res || (config.symbolNode.animationIndex < 0)) {
306 ROSEN_LOGD("[%{public}s] invalid initial parameter", __func__);
307 continue;
308 }
309 if (parameters.size() <= static_cast<size_t>(config.symbolNode.animationIndex) ||
310 parameters[config.symbolNode.animationIndex].empty()) {
311 ROSEN_LOGD("[%{public}s] invalid parameter", __func__);
312 continue;
313 }
314 auto canvasNode = rsNode->canvasNodesListMap_[symbolAnimationConfig->symbolSpanId][config.nodeId];
315 SpliceAnimation(canvasNode, parameters[config.symbolNode.animationIndex]);
316 }
317 {
318 std::lock_guard<std::mutex> lock(rsNode->childrenNodeLock_);
319 swap(rsNode->replaceNodesSwapArr_[INVALID_STATUS], rsNode->replaceNodesSwapArr_[APPEAR_STATUS]);
320 }
321 return true;
322 }
323
SetReplaceAppear(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig,const std::shared_ptr<RSNode> & rsNode,bool isStartAnimation)324 bool RSSymbolAnimation::SetReplaceAppear(
325 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig,
326 const std::shared_ptr<RSNode>& rsNode,
327 bool isStartAnimation)
328 {
329 if (symbolAnimationConfig->symbolNodes.empty()) {
330 ROSEN_LOGD("[%{public}s] symbol nodes is empty", __func__);
331 return false;
332 }
333 const auto& symbolFirstNode = symbolAnimationConfig->symbolNodes[0]; // calculate offset by the first node
334 Vector4f offsets = CalculateOffset(symbolFirstNode.symbolData.path_,
335 symbolFirstNode.nodeBoundary[0], symbolFirstNode.nodeBoundary[1]); // index 0 offsetX and 1 offsetY of layout
336 std::vector<std::vector<Drawing::DrawingPiecewiseParameter>> parameters;
337 bool res = GetAnimationGroupParameters(symbolAnimationConfig, parameters, symbolAnimationConfig->effectStrategy);
338 uint32_t nodeNum = symbolAnimationConfig->numNodes;
339 rsNode->replaceNodesSwapArr_[APPEAR_STATUS].resize(nodeNum);
340 for (uint32_t n = 0; n < nodeNum; n++) {
341 auto& symbolNode = symbolAnimationConfig->symbolNodes[n];
342 auto bounds = Vector4f(offsets[0], offsets[1], symbolNode.nodeBoundary[NODE_WIDTH],
343 symbolNode.nodeBoundary[NODE_HEIGHT]);
344 std::shared_ptr<RSCanvasNode> canvasNode = nullptr;
345 bool createNewNode = CreateSymbolReplaceNode(symbolAnimationConfig, bounds, n, rsNode, canvasNode);
346 if (canvasNode == nullptr) {
347 return false;
348 }
349 GroupDrawing(canvasNode, symbolNode, offsets);
350 bool isInValid = !res || !isStartAnimation || symbolNode.animationIndex < 0 ||
351 parameters.size() <= static_cast<size_t>(symbolNode.animationIndex);
352 if (isInValid) {
353 ROSEN_LOGD("[%{public}s] invalid animationIndex or parameter", __func__);
354 continue;
355 }
356
357 if (createNewNode) {
358 SpliceAnimation(canvasNode, parameters[symbolNode.animationIndex]);
359 }
360 }
361 return true;
362 }
363
CreateSymbolNode(const Vector4f & bounds,uint64_t symbolSpanId,uint32_t index,const std::shared_ptr<RSNode> & rsNode,std::shared_ptr<RSCanvasNode> & canvasNode)364 bool RSSymbolAnimation::CreateSymbolNode(const Vector4f& bounds, uint64_t symbolSpanId, uint32_t index,
365 const std::shared_ptr<RSNode>& rsNode, std::shared_ptr<RSCanvasNode>& canvasNode)
366 {
367 if (rsNode == nullptr) {
368 return false;
369 }
370 std::lock_guard<std::mutex> lock(rsNode->childrenNodeLock_);
371 bool createNewNode = false;
372 auto outerIter = rsNode->canvasNodesListMap_.find(symbolSpanId);
373 if (outerIter == rsNode->canvasNodesListMap_.end()) {
374 outerIter = rsNode->canvasNodesListMap_.insert({symbolSpanId,
375 std::unordered_map<NodeId, std::shared_ptr<RSNode>>()}).first;
376 createNewNode = true;
377 }
378
379 NodeId nodeId = static_cast<NodeId>(index);
380 createNewNode = createNewNode || outerIter->second.find(nodeId) == outerIter->second.end();
381 if (!createNewNode) {
382 UpdateSymbolGeometry(rsNode->canvasNodesListMap_[symbolSpanId][nodeId], bounds);
383 canvasNode = std::static_pointer_cast<RSCanvasNode>(rsNode->canvasNodesListMap_[symbolSpanId][nodeId]);
384 return false;
385 }
386 canvasNode = RSCanvasNode::Create(false, false, rsNode->GetRSUIContext());
387 outerIter->second.insert({nodeId, canvasNode});
388 SetSymbolGeometry(canvasNode, bounds);
389 rsNode->AddChild(canvasNode, -1);
390 return true;
391 }
392
CreateSymbolReplaceNode(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig,const Vector4f & bounds,uint32_t index,const std::shared_ptr<RSNode> & rsNode,std::shared_ptr<RSCanvasNode> & canvasNode)393 bool RSSymbolAnimation::CreateSymbolReplaceNode(
394 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig,
395 const Vector4f& bounds, uint32_t index, const std::shared_ptr<RSNode>& rsNode,
396 std::shared_ptr<RSCanvasNode>& canvasNode)
397 {
398 if (rsNode == nullptr) {
399 return false;
400 }
401 std::lock_guard<std::mutex> lock(rsNode->childrenNodeLock_);
402
403 bool createNewNode = false;
404 auto symbolSpanId = symbolAnimationConfig->symbolSpanId;
405 auto outerIter = rsNode->canvasNodesListMap_.find(symbolSpanId);
406 if (outerIter == rsNode->canvasNodesListMap_.end()) {
407 outerIter = rsNode->canvasNodesListMap_.insert({symbolSpanId,
408 std::unordered_map<NodeId, std::shared_ptr<RSNode>>()}).first;
409 createNewNode = true;
410 }
411 NodeId nodeId = rsNode->replaceNodesSwapArr_[APPEAR_STATUS][index].nodeId;
412 createNewNode = createNewNode || outerIter->second.find(nodeId) == outerIter->second.end() ||
413 rsNode->replaceNodesSwapArr_[APPEAR_STATUS][index].animationIndex < 0;
414 if (!createNewNode) {
415 UpdateSymbolGeometry(rsNode->canvasNodesListMap_[symbolSpanId][nodeId], bounds);
416 canvasNode = std::static_pointer_cast<RSCanvasNode>(rsNode->canvasNodesListMap_[symbolSpanId][nodeId]);
417 return false;
418 }
419
420 canvasNode = RSCanvasNode::Create(false, false, rsNode->GetRSUIContext());
421 nodeId = canvasNode->GetId();
422 outerIter->second.insert({nodeId, canvasNode});
423 SetSymbolGeometry(canvasNode, bounds);
424 rsNode->AddChild(canvasNode, -1);
425 auto& symbolNode = symbolAnimationConfig->symbolNodes[index];
426 AnimationNodeConfig appearNodeConfig = {.symbolNode = symbolNode,
427 .nodeId = nodeId,
428 .animationIndex = symbolNode.animationIndex};
429 rsNode->replaceNodesSwapArr_[APPEAR_STATUS][index] = appearNodeConfig;
430 return true;
431 }
432
InitSupportAnimationTable(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig)433 void RSSymbolAnimation::InitSupportAnimationTable(
434 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig)
435 {
436 // Init public animation list
437 if (publicSupportAnimations_.empty()) {
438 publicSupportAnimations_ = {Drawing::DrawingEffectStrategy::BOUNCE,
439 Drawing::DrawingEffectStrategy::APPEAR,
440 Drawing::DrawingEffectStrategy::DISAPPEAR,
441 Drawing::DrawingEffectStrategy::SCALE};
442 }
443 if (upAndDownSupportAnimations_.empty()) {
444 upAndDownSupportAnimations_ = {Drawing::DrawingEffectStrategy::BOUNCE,
445 Drawing::DrawingEffectStrategy::SCALE,
446 Drawing::DrawingEffectStrategy::DISABLE};
447 }
448
449 range_ = std::nullopt;
450 Vector4f bounds = rsNode_->GetStagingProperties().GetBounds();
451 symbolBounds_ = Vector4f(0.0f, 0.0f, bounds.z_, bounds.w_);
452 isMaskSymbol_ = false;
453 for (const auto& symbolNode: symbolAnimationConfig->symbolNodes) {
454 if (symbolNode.isMask) {
455 isMaskSymbol_ = true;
456 return;
457 }
458 }
459 }
460
GetAnimationGroupParameters(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig,std::vector<std::vector<Drawing::DrawingPiecewiseParameter>> & parameters,Drawing::DrawingEffectStrategy & effectStrategy)461 bool RSSymbolAnimation::GetAnimationGroupParameters(
462 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig,
463 std::vector<std::vector<Drawing::DrawingPiecewiseParameter>>& parameters,
464 Drawing::DrawingEffectStrategy& effectStrategy)
465 {
466 // count animation levels
467 int animationLevelNum = -1;
468 auto nodeNum = symbolAnimationConfig->numNodes;
469 for (uint32_t n = 0; n < nodeNum; n++) {
470 const auto& symbolNode = symbolAnimationConfig->symbolNodes[n];
471 animationLevelNum =
472 animationLevelNum < symbolNode.animationIndex ? symbolNode.animationIndex : animationLevelNum;
473 }
474
475 if (animationLevelNum < 0) {
476 ROSEN_LOGD("[%{public}s] HmSymbol: this symbol does not have an animated layer", __func__);
477 return false;
478 }
479 animationLevelNum = animationLevelNum + 1;
480
481 // get animation group paramaters
482 auto it = std::find(upAndDownSupportAnimations_.begin(), upAndDownSupportAnimations_.end(), effectStrategy);
483 if (it != upAndDownSupportAnimations_.end()) {
484 parameters = OHOS::Rosen::Symbol::DefaultSymbolConfig::GetInstance()->GetGroupParameters(
485 Drawing::DrawingAnimationType(effectStrategy), static_cast<uint16_t>(animationLevelNum),
486 symbolAnimationConfig->animationMode, symbolAnimationConfig->commonSubType);
487 } else {
488 parameters = OHOS::Rosen::Symbol::DefaultSymbolConfig::GetInstance()->GetGroupParameters(
489 Drawing::DrawingAnimationType(effectStrategy), static_cast<uint16_t>(animationLevelNum),
490 symbolAnimationConfig->animationMode);
491 }
492 if (parameters.empty()) {
493 ROSEN_LOGD("[%{public}s] HmSymbol: GetGroupParameters failed", __func__);
494 return false;
495 }
496 return true;
497 }
498
ChooseAnimation(const std::shared_ptr<RSNode> & rsNode,std::vector<Drawing::DrawingPiecewiseParameter> & parameters,const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig)499 bool RSSymbolAnimation::ChooseAnimation(const std::shared_ptr<RSNode>& rsNode,
500 std::vector<Drawing::DrawingPiecewiseParameter>& parameters,
501 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig)
502 {
503 if (std::count(publicSupportAnimations_.begin(),
504 publicSupportAnimations_.end(), symbolAnimationConfig->effectStrategy) != 0) {
505 SpliceAnimation(rsNode, parameters);
506 return true;
507 }
508
509 switch (symbolAnimationConfig->effectStrategy) {
510 case Drawing::DrawingEffectStrategy::VARIABLE_COLOR:
511 return SetKeyframeAlphaAnimation(rsNode, parameters, symbolAnimationConfig);
512 case Drawing::DrawingEffectStrategy::PULSE:
513 return SetKeyframeAlphaAnimation(rsNode, parameters, symbolAnimationConfig);
514 default:
515 ROSEN_LOGD("[%{public}s] not support input animation type", __func__);
516 return false;
517 }
518 }
519
SetSymbolShadow(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig,std::shared_ptr<RSNode> & rsNode,const std::shared_ptr<RSNode> & rsNodeRoot)520 void RSSymbolAnimation::SetSymbolShadow(
521 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig,
522 std::shared_ptr<RSNode>& rsNode,
523 const std::shared_ptr<RSNode>& rsNodeRoot)
524 {
525 if (!symbolAnimationConfig->symbolShadow.has_value()) {
526 return;
527 }
528 if (rsNodeRoot == nullptr) {
529 return;
530 }
531 // update bounds
532 auto symbolBounds = symbolBounds_;
533 if (std::count(upAndDownSupportAnimations_.begin(), upAndDownSupportAnimations_.end(),
534 symbolAnimationConfig->effectStrategy) != 0) {
535 float x = symbolAnimationConfig->symbolNodes[0].nodeBoundary[NODE_WIDTH] * EXPANSION_RATIO;
536 float y = symbolAnimationConfig->symbolNodes[0].nodeBoundary[NODE_HEIGHT] * EXPANSION_RATIO;
537 float two = 2; // 2 is two
538 symbolBounds = Vector4f(-x, -y, symbolBounds_.z_ + y * two, symbolBounds_.w_ + x * two);
539 }
540
541 std::shared_ptr<RSCanvasNode> canvasNode;
542 CreateSymbolNode(symbolBounds, symbolAnimationConfig->symbolSpanId,
543 symbolAnimationConfig->symbolSpanId, rsNodeRoot, canvasNode);
544 if (canvasNode == nullptr) {
545 ROSEN_LOGE("Failed to create rsNode");
546 return;
547 }
548 rsNode = canvasNode;
549 rsNode->SetClipToBounds(false);
550 rsNode->SetClipToFrame(false);
551 for (auto& symbolNode: symbolAnimationConfig->symbolNodes) {
552 symbolNode.nodeBoundary[0] -= symbolBounds[0];
553 symbolNode.nodeBoundary[1] -= symbolBounds[1];
554 }
555 symbolBounds_.z_ = symbolBounds.z_;
556 symbolBounds_.w_ = symbolBounds.w_;
557
558 // set symbolShadow
559 auto symbolShadow = symbolAnimationConfig->symbolShadow.value();
560 SetSymbolShadow(symbolShadow, rsNode);
561 return;
562 }
563
SetSymbolShadow(const SymbolShadow & symbolShadow,std::shared_ptr<RSNode> & rsNode)564 void RSSymbolAnimation::SetSymbolShadow(const SymbolShadow& symbolShadow, std::shared_ptr<RSNode>& rsNode)
565 {
566 rsNode->SetShadowColor(symbolShadow.color.CastToColorQuad());
567 rsNode->SetShadowOffset(symbolShadow.offset.GetX(), symbolShadow.offset.GetY());
568 rsNode->SetShadowRadius(symbolShadow.blurRadius);
569 rsNode->SetShadowMaskStrategy(SHADOW_MASK_STRATEGY::MASK_COLOR_BLUR);
570 }
571
SetPublicAnimation(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig)572 bool RSSymbolAnimation::SetPublicAnimation(
573 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig)
574 {
575 if (symbolAnimationConfig->symbolNodes.empty()) {
576 ROSEN_LOGD("[%{public}s] symbol nodes is empty", __func__);
577 return false;
578 }
579 auto symbolSpanId = symbolAnimationConfig->symbolSpanId;
580 std::shared_ptr<RSNode> rsNode = rsNode_;
581 SetSymbolShadow(symbolAnimationConfig, rsNode, rsNode_);
582 if (isMaskSymbol_) {
583 std::shared_ptr<RSNode> rsNodeMask = nullptr;
584 CreateSameNode(symbolSpanId, rsNodeMask, rsNode);
585 if (rsNodeMask == nullptr) {
586 ROSEN_LOGE("Failed to create rsNode");
587 return false;
588 }
589 rsNodeMask->SetColorBlendMode(RSColorBlendMode::SRC_OVER);
590 rsNodeMask->SetColorBlendApplyType(RSColorBlendApplyType::SAVE_LAYER_ALPHA);
591 rsNode = rsNodeMask;
592 }
593
594 const auto& symbolFirstNode = symbolAnimationConfig->symbolNodes[0]; // calculate offset by the first node
595 Vector4f offsets = CalculateOffset(symbolFirstNode.symbolData.path_, symbolFirstNode.nodeBoundary[0],
596 symbolFirstNode.nodeBoundary[1]); // index 0 offsetX and 1 offsetY of layout
597 std::vector<std::vector<Drawing::DrawingPiecewiseParameter>> parameters;
598 bool res = GetAnimationGroupParameters(symbolAnimationConfig, parameters, symbolAnimationConfig->effectStrategy);
599 uint32_t nodeNum = symbolAnimationConfig->numNodes;
600 for (uint32_t n = 0; n < nodeNum; n++) {
601 auto& symbolNode = symbolAnimationConfig->symbolNodes[n];
602 auto bounds = Vector4f(offsets[0], offsets[1], symbolNode.nodeBoundary[NODE_WIDTH],
603 symbolNode.nodeBoundary[NODE_HEIGHT]);
604 std::shared_ptr<RSCanvasNode> canvasNode = nullptr;
605 bool createNewNode = CreateSymbolNode(bounds, symbolSpanId, n, rsNode, canvasNode);
606 if (canvasNode == nullptr) {
607 return false;
608 }
609 GroupDrawing(canvasNode, symbolNode, offsets);
610
611 bool isInValid = !res || symbolNode.animationIndex < 0 ||
612 parameters.size() <= static_cast<size_t>(symbolNode.animationIndex);
613 if (isInValid) {
614 ROSEN_LOGD("[%{public}s] invalid animationIndex or parameter", __func__);
615 continue;
616 }
617
618 if (createNewNode) {
619 ChooseAnimation(canvasNode, parameters[symbolNode.animationIndex], symbolAnimationConfig);
620 }
621 }
622 return true;
623 }
624
625 // set text flip animation
SetTextFlipAnimation(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig)626 bool RSSymbolAnimation::SetTextFlipAnimation(
627 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig)
628 {
629 if (!symbolAnimationConfig->animationStart) {
630 ROSEN_LOGD("Clear all text animation");
631 std::lock_guard<std::mutex> lock(rsNode_->childrenNodeLock_);
632 rsNode_->canvasNodesListMap_.clear();
633 return true;
634 }
635 if (symbolAnimationConfig->parameters.size() < PROPERTIES) {
636 ROSEN_LOGE("Invalid animation parameters of text flip, parameters.size: %{public}zu ",
637 symbolAnimationConfig->parameters.size());
638 return false;
639 }
640
641 FrameRateRange range = {60, 60, 60}; // The fixed frame rate is 60 of text flip animation
642 range_ = range;
643 if (!symbolAnimationConfig->currentAnimationHasPlayed) {
644 SetFlipDisappear(symbolAnimationConfig, rsNode_);
645 }
646 return SetFlipAppear(symbolAnimationConfig, rsNode_,
647 !symbolAnimationConfig->currentAnimationHasPlayed);
648 }
649
SetFlipDisappear(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig,std::shared_ptr<RSNode> & rsNode)650 void RSSymbolAnimation::SetFlipDisappear(
651 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig,
652 std::shared_ptr<RSNode>& rsNode)
653 {
654 const auto& symbolId = symbolAnimationConfig->symbolSpanId;
655 if (rsNode->canvasNodesListMap_.find(symbolId) == rsNode->canvasNodesListMap_.end()) {
656 return ;
657 }
658 if (rsNode->canvasNodesListMap_[symbolId].find(APPEAR_STATUS) == rsNode->canvasNodesListMap_[symbolId].end()) {
659 return;
660 }
661 auto& canvasNode = rsNode->canvasNodesListMap_[symbolId][APPEAR_STATUS];
662 auto parameter = UpdateParametersDelay(symbolAnimationConfig->parameters[0],
663 symbolAnimationConfig->effectElement.delay);
664 SpliceAnimation(canvasNode, parameter);
665 {
666 std::lock_guard<std::mutex> lock(rsNode->childrenNodeLock_);
667 rsNode->canvasNodesListMap_[symbolId].insert({INVALID_STATUS, canvasNode});
668 rsNode->canvasNodesListMap_[symbolId].erase(APPEAR_STATUS);
669 }
670 }
671
SetFlipAppear(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig,std::shared_ptr<RSNode> & rsNode,bool isStartAnimation)672 bool RSSymbolAnimation::SetFlipAppear(
673 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig,
674 std::shared_ptr<RSNode>& rsNode, bool isStartAnimation)
675 {
676 auto symbolSpanId = symbolAnimationConfig->symbolSpanId;
677 TextEngine::SymbolNode symbolNode;
678 const auto& effectNode = symbolAnimationConfig->effectElement;
679 if (!effectNode.path.IsValid()) {
680 return true;
681 }
682 // creat childNode
683 Vector4f offsets = CalculateOffset(effectNode.path, effectNode.offset.GetX(),
684 effectNode.offset.GetY());
685 // 0: offsetX, 1: offsetY of childNode
686 auto bounds = Vector4f(offsets[0], offsets[1], effectNode.width, effectNode.height);
687 std::shared_ptr<RSCanvasNode> canvasNode = nullptr;
688 isStartAnimation = CreateSymbolNode(bounds, symbolSpanId, APPEAR_STATUS, rsNode, canvasNode);
689 if (canvasNode == nullptr) {
690 ROSEN_LOGE("Failed to get canvasNode of TextFilp");
691 return false;
692 }
693 // draw path
694 auto recordingCanvas = canvasNode->BeginRecording(effectNode.width, effectNode.height);
695 DrawPathOnCanvas(recordingCanvas, effectNode, symbolAnimationConfig->color, {offsets[0], offsets[1]});
696 canvasNode->FinishRecording();
697 if (isStartAnimation) {
698 auto parameter = UpdateParametersDelay(symbolAnimationConfig->parameters[1], effectNode.delay);
699 SpliceAnimation(canvasNode, parameter);
700 }
701 return true;
702 }
703
UpdateParametersDelay(const std::vector<Drawing::DrawingPiecewiseParameter> & parameters,int delay)704 std::vector<Drawing::DrawingPiecewiseParameter> RSSymbolAnimation::UpdateParametersDelay(
705 const std::vector<Drawing::DrawingPiecewiseParameter>& parameters, int delay)
706 {
707 std::vector<Drawing::DrawingPiecewiseParameter> outParameters = parameters;
708 for (auto& parameter : outParameters) {
709 parameter.delay += delay;
710 }
711 return outParameters;
712 }
713
DrawPathOnCanvas(ExtendRecordingCanvas * recordingCanvas,const TextEngine::TextEffectElement & effectNode,const Drawing::Color & color,const Drawing::Point & offset)714 void RSSymbolAnimation::DrawPathOnCanvas(ExtendRecordingCanvas* recordingCanvas,
715 const TextEngine::TextEffectElement& effectNode,
716 const Drawing::Color& color, const Drawing::Point& offset)
717 {
718 if (recordingCanvas == nullptr) {
719 return;
720 }
721
722 Drawing::Brush brush;
723 brush.SetAntiAlias(true);
724 brush.SetColor(color.CastToColorQuad());
725 auto path = effectNode.path;
726 path.Offset(effectNode.offset.GetX() - offset.GetX(), effectNode.offset.GetY() - offset.GetY());
727 recordingCanvas->AttachBrush(brush);
728 recordingCanvas->DrawPath(path);
729 recordingCanvas->DetachBrush();
730 }
731
GroupAnimationStart(const std::shared_ptr<RSNode> & rsNode,std::vector<std::shared_ptr<RSAnimation>> & animations)732 void RSSymbolAnimation::GroupAnimationStart(
733 const std::shared_ptr<RSNode>& rsNode, std::vector<std::shared_ptr<RSAnimation>>& animations)
734 {
735 if (rsNode == nullptr || animations.empty()) {
736 ROSEN_LOGD("[%{public}s] : invalid input", __func__);
737 return;
738 }
739
740 for (int i = 0; i < static_cast<int>(animations.size()); i++) {
741 if (animations[i]) {
742 animations[i]->Start(rsNode);
743 }
744 }
745 }
746
SetNodePivot(const std::shared_ptr<RSNode> & rsNode)747 void RSSymbolAnimation::SetNodePivot(const std::shared_ptr<RSNode>& rsNode)
748 {
749 if (rsNode == nullptr) {
750 ROSEN_LOGD("Interpolator is null, return FRACTION_MIN.");
751 return;
752 }
753 // Set Node Center Offset
754 Vector2f curNodePivot = rsNode->GetStagingProperties().GetPivot();
755 pivotProperty_ = nullptr; // reset
756 if (!(curNodePivot.x_ == CENTER_NODE_COORDINATE.x_ && curNodePivot.y_ == CENTER_NODE_COORDINATE.y_)) {
757 SymbolAnimation::CreateOrSetModifierValue(pivotProperty_, CENTER_NODE_COORDINATE);
758 auto modifier = std::make_shared<ModifierNG::RSTransformModifier>();
759 modifier->AttachProperty(ModifierNG::RSPropertyType::PIVOT, pivotProperty_);
760 rsNode->AddModifier(modifier);
761 }
762 }
763
CreateSameNode(uint64_t symbolId,std::shared_ptr<RSNode> & rsNode,const std::shared_ptr<RSNode> & rsNodeRoot)764 void RSSymbolAnimation::CreateSameNode(uint64_t symbolId, std::shared_ptr<RSNode>& rsNode,
765 const std::shared_ptr<RSNode>& rsNodeRoot)
766 {
767 if (rsNodeRoot == nullptr) {
768 return;
769 }
770
771 const auto& symbolBounds = symbolBounds_;
772 std::lock_guard<std::mutex> lock(rsNodeRoot->childrenNodeLock_);
773 auto outerIter = rsNodeRoot->canvasNodesListMap_.find(symbolId);
774 if (outerIter == rsNodeRoot->canvasNodesListMap_.end()) {
775 outerIter = rsNodeRoot->canvasNodesListMap_.insert({symbolId,
776 std::unordered_map<NodeId, std::shared_ptr<RSNode>>()}).first;
777 }
778 if (outerIter->second.find(symbolId) == outerIter->second.end()) {
779 auto childNode = RSCanvasNode::Create(false, false, rsNodeRoot->GetRSUIContext());
780 SetSymbolGeometry(childNode, symbolBounds);
781 outerIter->second.insert({symbolId, childNode});
782 rsNodeRoot->AddChild(childNode, -1);
783 } else {
784 UpdateSymbolGeometry(outerIter->second[symbolId], symbolBounds);
785 }
786 rsNode = outerIter->second[symbolId];
787 }
788
789 // set Disable Animation
SetDisableAnimation(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig)790 bool RSSymbolAnimation::SetDisableAnimation(
791 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig)
792 {
793 if (symbolAnimationConfig->symbolNodes.size() < 1) { // 1: symbol nodes must be >= 1
794 ROSEN_LOGE("HmSymbol Failed to set disable animation, symbol size: %{public}zu",
795 symbolAnimationConfig->symbolNodes.size());
796 return false;
797 }
798
799 // get the disable animation paramters
800 std::vector<std::vector<Drawing::DrawingPiecewiseParameter>> parameters;
801 GetAnimationGroupParameters(symbolAnimationConfig, parameters, symbolAnimationConfig->effectStrategy);
802 std::shared_ptr<RSNode> rsNode = rsNode_;
803 SetSymbolShadow(symbolAnimationConfig, rsNode, rsNode_);
804 return SetDisableAnimation(symbolAnimationConfig, parameters, rsNode);
805 }
806
SetDisableAnimation(const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig,std::vector<std::vector<Drawing::DrawingPiecewiseParameter>> & parameters,const std::shared_ptr<RSNode> & rsNodeRoot)807 bool RSSymbolAnimation::SetDisableAnimation(
808 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig,
809 std::vector<std::vector<Drawing::DrawingPiecewiseParameter>>& parameters,
810 const std::shared_ptr<RSNode>& rsNodeRoot)
811 {
812 if (parameters.empty()) {
813 ROSEN_LOGE("HmSymbol Failed to get disable parameters");
814 return false;
815 }
816 SetDisableParameter(parameters[parameters.size() - 1], symbolAnimationConfig);
817
818 // Create a child node the same as the rsNode_
819 std::shared_ptr<RSNode> rsNode = nullptr;
820 CreateSameNode(symbolAnimationConfig->symbolSpanId, rsNode, rsNodeRoot);
821 if (rsNode == nullptr) {
822 ROSEN_LOGE("HmSymbol Failed to create rsNode");
823 return false;
824 }
825 rsNode->SetColorBlendMode(RSColorBlendMode::SRC_OVER);
826 rsNode->SetColorBlendApplyType(RSColorBlendApplyType::SAVE_LAYER_ALPHA);
827
828 // calculate offset by the first symbol node config
829 const auto& symbolFirstNode = symbolAnimationConfig->symbolNodes[0];
830 Vector4f offsets = CalculateOffset(symbolFirstNode.symbolData.path_, symbolFirstNode.nodeBoundary[0],
831 symbolFirstNode.nodeBoundary[1]); // index 0 offsetX, 1 offsety of layout
832 // set animation base layers
833 if (!SetDisableBaseLayer(rsNode, symbolAnimationConfig, parameters, offsets)) {
834 return false;
835 }
836
837 // set animation clip layer
838 uint32_t n = symbolAnimationConfig->symbolNodes.size() -1;
839 const auto& symbolNode = symbolAnimationConfig->symbolNodes[n];
840 bool isInValid = symbolNode.animationIndex < 0 || symbolNode.isMask ||
841 parameters.size() <= static_cast<size_t>(symbolNode.animationIndex);
842 if (isInValid) {
843 ROSEN_LOGE("Invalid parameter of clip layer in HmSymbol");
844 return false;
845 }
846 return SetClipAnimation(rsNodeRoot, symbolAnimationConfig, parameters[symbolNode.animationIndex], n, offsets);
847 }
848
849 // set disable parameter with slope of symbol
SetDisableParameter(std::vector<Drawing::DrawingPiecewiseParameter> & parameter,const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig)850 void RSSymbolAnimation::SetDisableParameter(std::vector<Drawing::DrawingPiecewiseParameter>& parameter,
851 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig)
852 {
853 if (parameter.empty()) {
854 return;
855 }
856 uint32_t n = symbolAnimationConfig->symbolNodes.size();
857 const auto& symbolNode = symbolAnimationConfig->symbolNodes[n - 1];
858 if (symbolNode.pathsInfo.empty()) {
859 return;
860 }
861
862 auto slope = symbolAnimationConfig->slope;
863 auto rect = symbolNode.pathsInfo[0].path.GetBounds();
864 float w = rect.GetWidth();
865 float h = rect.GetHeight();
866 float distance = std::sqrt(w * w + h * h);
867 float angle = std::atan(slope);
868 float x = std::cos(angle) * distance;
869 float y = std::sin(angle) * distance;
870 x = slope > 0 ? x * -1 : x; // -1: The direction of the x-axis needs to be reversed
871 y = slope < 0 ? y * -1 : y; // -1: The direction of the Y-axis needs to be reversed
872
873 for (auto& param: parameter) {
874 std::vector<float> ratio;
875 if (param.properties.count(TRANSLATE_RATIO)) {
876 ratio = param.properties[TRANSLATE_RATIO];
877 }
878 if (param.properties.count(CLIP_PROP)) {
879 ratio = param.properties[CLIP_PROP];
880 }
881 if (ratio.size() < PROPERTIES) {
882 continue;
883 }
884 param.properties.insert({TRANSLATE_PROP_X, {x * ratio[PROP_START], x * ratio[PROP_END]}});
885 param.properties.insert({TRANSLATE_PROP_Y, {y * ratio[PROP_START], y * ratio[PROP_END]}});
886 }
887 }
888
SetDisableBaseLayer(const std::shared_ptr<RSNode> & rsNode,const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig,const std::vector<std::vector<Drawing::DrawingPiecewiseParameter>> & parameters,const Vector4f & offsets)889 bool RSSymbolAnimation::SetDisableBaseLayer(const std::shared_ptr<RSNode>& rsNode,
890 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig,
891 const std::vector<std::vector<Drawing::DrawingPiecewiseParameter>>& parameters,
892 const Vector4f& offsets)
893 {
894 auto symbolId = symbolAnimationConfig->symbolSpanId;
895 for (uint32_t n = 0; n < symbolAnimationConfig->symbolNodes.size() -1; n++) {
896 auto& symbolNode = symbolAnimationConfig->symbolNodes[n];
897 auto bounds = Vector4f(offsets[0], offsets[1], symbolNode.nodeBoundary[NODE_WIDTH],
898 symbolNode.nodeBoundary[NODE_HEIGHT]);
899 std::shared_ptr<RSCanvasNode> canvasNode = nullptr;
900 bool createNewNode = CreateSymbolNode(bounds, symbolId, n, rsNode, canvasNode);
901 if (canvasNode == nullptr) {
902 ROSEN_LOGE("HmSymbol canvasNode is nullptr");
903 return false;
904 }
905 auto recordingCanvas = canvasNode->BeginRecording(symbolNode.nodeBoundary[NODE_WIDTH],
906 symbolNode.nodeBoundary[NODE_HEIGHT]);
907 DrawPathOnCanvas(recordingCanvas, symbolNode, offsets);
908 canvasNode->FinishRecording();
909
910 bool isInValid = symbolNode.animationIndex < 0 ||
911 parameters.size() <= static_cast<size_t>(symbolNode.animationIndex);
912 if (isInValid) {
913 continue;
914 }
915 if (createNewNode) {
916 SpliceAnimation(canvasNode, parameters[symbolNode.animationIndex]);
917 }
918 }
919 return true;
920 }
921
SetClipAnimation(const std::shared_ptr<RSNode> & rsNode,const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig,const std::vector<Drawing::DrawingPiecewiseParameter> & parameters,uint32_t index,const Vector4f & offsets)922 bool RSSymbolAnimation::SetClipAnimation(const std::shared_ptr<RSNode>& rsNode,
923 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig,
924 const std::vector<Drawing::DrawingPiecewiseParameter>& parameters,
925 uint32_t index, const Vector4f& offsets)
926 {
927 if (parameters.size() < 3) { // 3: the size of parameters for the disable animation must be >= 3
928 ROSEN_LOGD("Invalid clip parameter in HmSymbol");
929 return false;
930 }
931 // create clip layer node
932 auto symbolId = symbolAnimationConfig->symbolSpanId;
933 auto& symbolNode = symbolAnimationConfig->symbolNodes[index];
934 auto bounds = Vector4f(offsets[0], offsets[1], symbolNode.nodeBoundary[NODE_WIDTH],
935 symbolNode.nodeBoundary[NODE_HEIGHT]);
936 std::shared_ptr<RSCanvasNode> canvasNode = nullptr;
937 bool createNewNode = CreateSymbolNode(bounds, symbolId, index, rsNode, canvasNode);
938 if (canvasNode == nullptr) {
939 ROSEN_LOGE("HmSymbol canvasNode is nullptr");
940 return false;
941 }
942 GroupDrawing(canvasNode, symbolNode, offsets, true);
943
944 // create a node that displays slashes
945 auto symbolBounds = Vector4f(0.0f, 0.0f, symbolNode.nodeBoundary[NODE_WIDTH],
946 symbolNode.nodeBoundary[NODE_HEIGHT]);
947 std::shared_ptr<RSCanvasNode> canvasNodeLine = nullptr;
948 createNewNode = CreateSymbolNode(symbolBounds, symbolId, index, canvasNode, canvasNodeLine);
949 if (canvasNodeLine == nullptr) {
950 ROSEN_LOGE("HmSymbol canvasNode is nullptr");
951 return false;
952 }
953 GroupDrawing(canvasNodeLine, symbolNode, offsets, false);
954 // set animation to clip layer
955 if (createNewNode) {
956 std::vector<Drawing::DrawingPiecewiseParameter> firstParameters;
957 uint32_t n = parameters.size() - 1; // the max index of parameters
958 for (uint32_t i = 0; i < n; i++) {
959 firstParameters.push_back(parameters[i]);
960 }
961 SpliceAnimation(canvasNode, firstParameters);
962 std::vector<Drawing::DrawingPiecewiseParameter> secondParameters = { parameters[n] };
963 SpliceAnimation(canvasNodeLine, secondParameters);
964 }
965 return true;
966 }
967
SpliceAnimation(const std::shared_ptr<RSNode> & rsNode,const std::vector<Drawing::DrawingPiecewiseParameter> & parameters)968 void RSSymbolAnimation::SpliceAnimation(const std::shared_ptr<RSNode>& rsNode,
969 const std::vector<Drawing::DrawingPiecewiseParameter>& parameters)
970 {
971 if (rsNode == nullptr) {
972 ROSEN_LOGD("RsNode is null, failed to SpliceAnimation.");
973 return;
974 }
975 std::shared_ptr<RSAnimatableProperty<Vector2f>> scaleProperty = nullptr;
976 std::shared_ptr<RSAnimatableProperty<float>> alphaProperty = nullptr;
977 std::shared_ptr<RSAnimatableProperty<Vector2f>> translateProperty = nullptr;
978 std::shared_ptr<RSAnimatableProperty<float>> blurProperty = nullptr;
979 std::shared_ptr<RSAnimatableProperty<Vector2f>> clipProperty = nullptr;
980 std::vector<std::shared_ptr<RSAnimation>> groupAnimation = {};
981 SymbolBaseFuncMap funcMap = {
982 {SCALE_PROP_X, [&, this](const Drawing::DrawingPiecewiseParameter& parameter)
983 {
984 ScaleAnimationBase(rsNode, scaleProperty, parameter, groupAnimation);
985 }
986 },
987 {ALPHA_PROP, [&, this](const Drawing::DrawingPiecewiseParameter& parameter)
988 {
989 AlphaAnimationBase(rsNode, alphaProperty, parameter, groupAnimation);
990 }
991 },
992 {TRANSLATE_PROP_X, [&, this](const Drawing::DrawingPiecewiseParameter& parameter)
993 {
994 TranslateAnimationBase(rsNode, translateProperty, parameter, groupAnimation);
995 }
996 },
997 {BLUR_PROP, [&, this](const Drawing::DrawingPiecewiseParameter& parameter)
998 {
999 BlurAnimationBase(rsNode, blurProperty, parameter, groupAnimation);
1000 }
1001 },
1002 {CLIP_PROP, [&, this](const Drawing::DrawingPiecewiseParameter& parameter)
1003 {
1004 TranslateAnimationBase(rsNode, clipProperty, parameter, groupAnimation);
1005 }
1006 }
1007 };
1008
1009 for (const auto& parameter : parameters) {
1010 for (const auto& pair : parameter.properties) {
1011 if (funcMap.count(pair.first) > 0) {
1012 funcMap[pair.first](parameter);
1013 break;
1014 }
1015 }
1016 }
1017 GroupAnimationStart(rsNode, groupAnimation);
1018 }
1019
CalculateOffset(const Drawing::Path & path,const float offsetX,const float offsetY)1020 Vector4f RSSymbolAnimation::CalculateOffset(const Drawing::Path& path, const float offsetX, const float offsetY)
1021 {
1022 auto rect = path.GetBounds();
1023 float left = rect.GetLeft();
1024 float top = rect.GetTop();
1025 // the nodeTranslation is offset of new node to the father node;
1026 // the newOffset is offset of path on new node;
1027 Vector2f nodeTranslation = { offsetX + left, offsetY + top };
1028 Vector2f newOffset = { -left, -top };
1029 return Vector4f(nodeTranslation[0], nodeTranslation[1], newOffset[0], newOffset[1]);
1030 }
1031
UpdateSymbolGeometry(const std::shared_ptr<RSNode> & rsNode,const Vector4f & bounds)1032 void RSSymbolAnimation::UpdateSymbolGeometry(const std::shared_ptr<RSNode>& rsNode, const Vector4f& bounds)
1033 {
1034 if (rsNode == nullptr) {
1035 return;
1036 }
1037 rsNode->SetBounds(bounds);
1038 rsNode->SetFrame(bounds);
1039 }
1040
GroupDrawing(const std::shared_ptr<RSCanvasNode> & canvasNode,TextEngine::SymbolNode & symbolNode,const Vector4f & offsets,bool isClip)1041 void RSSymbolAnimation::GroupDrawing(const std::shared_ptr<RSCanvasNode>& canvasNode,
1042 TextEngine::SymbolNode& symbolNode, const Vector4f& offsets, bool isClip)
1043 {
1044 // drawing a symbol or a path group
1045 auto recordingCanvas = canvasNode->BeginRecording(symbolNode.nodeBoundary[NODE_WIDTH],
1046 symbolNode.nodeBoundary[NODE_HEIGHT]);
1047 if (isClip) {
1048 DrawClipOnCanvas(recordingCanvas, symbolNode, offsets);
1049 } else {
1050 DrawPathOnCanvas(recordingCanvas, symbolNode, offsets);
1051 }
1052 canvasNode->FinishRecording();
1053 }
1054
DrawPathOnCanvas(ExtendRecordingCanvas * recordingCanvas,TextEngine::SymbolNode & symbolNode,const Vector4f & offsets)1055 void RSSymbolAnimation::DrawPathOnCanvas(
1056 ExtendRecordingCanvas* recordingCanvas, TextEngine::SymbolNode& symbolNode, const Vector4f& offsets)
1057 {
1058 if (recordingCanvas == nullptr) {
1059 return;
1060 }
1061 Drawing::Brush brush;
1062 Drawing::Pen pen;
1063 brush.SetAntiAlias(true);
1064 pen.SetAntiAlias(true);
1065 Drawing::Point offset = Drawing::Point(offsets[2], offsets[3]); // index 2 offsetX 3 offsetY
1066 if (symbolNode.isMask) {
1067 brush.SetBlendMode(Drawing::BlendMode::CLEAR);
1068 pen.SetBlendMode(Drawing::BlendMode::CLEAR);
1069 recordingCanvas->AttachBrush(brush);
1070 recordingCanvas->AttachPen(pen);
1071 for (auto pathInfo: symbolNode.pathsInfo) {
1072 pathInfo.path.Offset(offset.GetX(), offset.GetY());
1073 recordingCanvas->DrawPath(pathInfo.path);
1074 }
1075 recordingCanvas->DetachBrush();
1076 recordingCanvas->DetachPen();
1077 return;
1078 }
1079
1080 for (auto pathInfo: symbolNode.pathsInfo) {
1081 if (pathInfo.color == nullptr) {
1082 continue;
1083 }
1084 brush = pathInfo.color->CreateGradientBrush(offset);
1085 pen = pathInfo.color->CreateGradientPen(offset);
1086 pathInfo.path.Offset(offset.GetX(), offset.GetY());
1087 recordingCanvas->AttachBrush(brush);
1088 recordingCanvas->AttachPen(pen);
1089 recordingCanvas->DrawPath(pathInfo.path);
1090 recordingCanvas->DetachBrush();
1091 recordingCanvas->DetachPen();
1092 }
1093 }
1094
DrawClipOnCanvas(ExtendRecordingCanvas * recordingCanvas,TextEngine::SymbolNode & symbolNode,const Vector4f & offsets)1095 void RSSymbolAnimation::DrawClipOnCanvas(
1096 ExtendRecordingCanvas* recordingCanvas, TextEngine::SymbolNode& symbolNode, const Vector4f& offsets)
1097 {
1098 if (recordingCanvas == nullptr) {
1099 return;
1100 }
1101 Drawing::Brush brush;
1102 Drawing::Pen pen;
1103 brush.SetAntiAlias(true);
1104 pen.SetAntiAlias(true);
1105 recordingCanvas->AttachBrush(brush);
1106 recordingCanvas->AttachPen(pen);
1107
1108 for (auto pathInfo: symbolNode.pathsInfo) {
1109 pathInfo.path.Offset(offsets[2], offsets[3]); // index 2 offsetX 3 offsetY
1110 recordingCanvas->ClipPath(pathInfo.path, Drawing::ClipOp::INTERSECT, true);
1111 }
1112 recordingCanvas->DetachBrush();
1113 recordingCanvas->DetachPen();
1114 }
1115
SetSymbolGeometry(const std::shared_ptr<RSNode> & rsNode,const Vector4f & bounds)1116 bool RSSymbolAnimation::SetSymbolGeometry(const std::shared_ptr<RSNode>& rsNode, const Vector4f& bounds)
1117 {
1118 if (rsNode == nullptr) {
1119 return false;
1120 }
1121 auto frameModifier = std::make_shared<ModifierNG::RSFrameModifier>();
1122 frameModifier->SetFrame(bounds);
1123 rsNode->AddModifier(frameModifier);
1124 auto boundsModifier = std::make_shared<ModifierNG::RSBoundsModifier>();
1125 boundsModifier->SetBounds(bounds);
1126 rsNode->AddModifier(boundsModifier);
1127 rsNode_->SetClipToBounds(false);
1128 rsNode_->SetClipToFrame(false);
1129 return true;
1130 }
1131
SetKeyframeAlphaAnimation(const std::shared_ptr<RSNode> & rsNode,std::vector<Drawing::DrawingPiecewiseParameter> & parameters,const std::shared_ptr<TextEngine::SymbolAnimationConfig> & symbolAnimationConfig)1132 bool RSSymbolAnimation::SetKeyframeAlphaAnimation(const std::shared_ptr<RSNode>& rsNode,
1133 std::vector<Drawing::DrawingPiecewiseParameter>& parameters,
1134 const std::shared_ptr<TextEngine::SymbolAnimationConfig>& symbolAnimationConfig)
1135 {
1136 if (rsNode == nullptr || symbolAnimationConfig == nullptr) {
1137 ROSEN_LOGD("HmSymbol SetVariableColorAnimation::getNode or get symbolAnimationConfig:failed");
1138 return false;
1139 }
1140 alphaPropertyStages_.clear();
1141 uint32_t duration = 0;
1142 std::vector<float> timePercents;
1143 if (!GetKeyframeAlphaAnimationParas(parameters, duration, timePercents)) {
1144 return false;
1145 }
1146 auto alphaModifier = std::make_shared<ModifierNG::RSAlphaModifier>();
1147 // 0 means the first stage of a node
1148 alphaModifier->AttachProperty(ModifierNG::RSPropertyType::ALPHA, alphaPropertyStages_[0]);
1149 rsNode->AddModifier(alphaModifier);
1150 std::shared_ptr<RSAnimation> animation = nullptr;
1151 animation = KeyframeAlphaSymbolAnimation(rsNode, parameters[0], duration, timePercents);
1152 if (animation == nullptr) {
1153 return false;
1154 }
1155
1156 if (symbolAnimationConfig->effectStrategy == Drawing::DrawingEffectStrategy::VARIABLE_COLOR &&
1157 symbolAnimationConfig->animationMode == 0) {
1158 animation->SetRepeatCount(1);
1159 } else {
1160 animation->SetRepeatCount(-1); // -1 means loop playback
1161 }
1162 animation->Start(rsNode);
1163 return true;
1164 }
1165
GetKeyframeAlphaAnimationParas(std::vector<Drawing::DrawingPiecewiseParameter> & oneGroupParas,uint32_t & totalDuration,std::vector<float> & timePercents)1166 bool RSSymbolAnimation::GetKeyframeAlphaAnimationParas(
1167 std::vector<Drawing::DrawingPiecewiseParameter>& oneGroupParas,
1168 uint32_t& totalDuration, std::vector<float>& timePercents)
1169 {
1170 if (oneGroupParas.empty()) {
1171 return false;
1172 }
1173 totalDuration = 0;
1174 // traverse all time stages
1175 for (size_t i = 0; i < oneGroupParas.size(); i++) {
1176 int interval = 0;
1177 if (i + 1 < oneGroupParas.size()) {
1178 interval = oneGroupParas[i + 1].delay -
1179 (static_cast<int>(oneGroupParas[i].duration) + oneGroupParas[i].delay);
1180 } else {
1181 interval = 0;
1182 }
1183 if (interval < 0) {
1184 return false;
1185 }
1186 totalDuration = oneGroupParas[i].duration + totalDuration + static_cast<uint32_t>(interval);
1187 if (!SymbolAnimation::ElementInMap(ALPHA_PROP, oneGroupParas[i].properties) ||
1188 oneGroupParas[i].properties[ALPHA_PROP].size() != PROPERTIES) {
1189 return false;
1190 }
1191 // the value of the key frame needs
1192 float alphaValueStart = oneGroupParas[i].properties[ALPHA_PROP][PROP_START];
1193 std::shared_ptr<RSAnimatableProperty<float>> alphaPropertyStart = nullptr;
1194 SymbolAnimation::CreateOrSetModifierValue(alphaPropertyStart, alphaValueStart);
1195 alphaPropertyStages_.push_back(alphaPropertyStart);
1196
1197 float alphaValueEnd = oneGroupParas[i].properties[ALPHA_PROP][PROP_END];
1198 std::shared_ptr<RSAnimatableProperty<float>> alphaPropertyEnd = nullptr;
1199 SymbolAnimation::CreateOrSetModifierValue(alphaPropertyEnd, alphaValueEnd);
1200 alphaPropertyStages_.push_back(alphaPropertyEnd);
1201 }
1202 return CalcTimePercents(timePercents, totalDuration, oneGroupParas);
1203 }
1204
CalcTimePercents(std::vector<float> & timePercents,const uint32_t totalDuration,const std::vector<Drawing::DrawingPiecewiseParameter> & oneGroupParas)1205 bool RSSymbolAnimation::CalcTimePercents(std::vector<float>& timePercents, const uint32_t totalDuration,
1206 const std::vector<Drawing::DrawingPiecewiseParameter>& oneGroupParas)
1207 {
1208 if (totalDuration == 0) {
1209 return false;
1210 }
1211 uint32_t duration = 0;
1212 timePercents.push_back(0); // the first property of timePercent
1213 for (int i = 0; i < static_cast<int>(oneGroupParas.size()) - 1; i++) {
1214 int interval = 0; // Interval between two animations
1215 duration = duration + oneGroupParas[i].duration;
1216 SymbolAnimation::CalcOneTimePercent(timePercents, totalDuration, duration);
1217 interval = oneGroupParas[i + 1].delay -
1218 (static_cast<int>(oneGroupParas[i].duration) + oneGroupParas[i].delay);
1219 if (interval < 0) {
1220 return false;
1221 }
1222 duration = duration + static_cast<uint32_t>(interval);
1223 SymbolAnimation::CalcOneTimePercent(timePercents, totalDuration, duration);
1224 }
1225 duration = duration + oneGroupParas.back().duration;
1226 SymbolAnimation::CalcOneTimePercent(timePercents, totalDuration, duration);
1227 return true;
1228 }
1229
SetIconProperty(Drawing::Brush & brush,Drawing::Pen & pen,Drawing::DrawingSColor & color)1230 void RSSymbolAnimation::SetIconProperty(Drawing::Brush& brush, Drawing::Pen& pen, Drawing::DrawingSColor& color)
1231 {
1232 brush.SetColor(Drawing::Color::ColorQuadSetARGB(0xFF, color.r, color.g, color.b));
1233 brush.SetAlphaF(color.a);
1234 brush.SetAntiAlias(true);
1235
1236 pen.SetColor(Drawing::Color::ColorQuadSetARGB(0xFF, color.r, color.g, color.b));
1237 pen.SetAlphaF(color.a);
1238 pen.SetAntiAlias(true);
1239 return;
1240 }
1241
KeyframeAlphaSymbolAnimation(const std::shared_ptr<RSNode> & rsNode,const Drawing::DrawingPiecewiseParameter & oneStageParas,const uint32_t duration,const std::vector<float> & timePercents)1242 std::shared_ptr<RSAnimation> RSSymbolAnimation::KeyframeAlphaSymbolAnimation(const std::shared_ptr<RSNode>& rsNode,
1243 const Drawing::DrawingPiecewiseParameter& oneStageParas, const uint32_t duration,
1244 const std::vector<float>& timePercents)
1245 {
1246 if (alphaPropertyStages_.size() == 0 || timePercents.size() != alphaPropertyStages_.size()) {
1247 return nullptr;
1248 }
1249 auto keyframeAnimation = std::make_shared<RSKeyframeAnimation>(alphaPropertyStages_[0]); // initial the alpha status
1250 if (keyframeAnimation == nullptr || rsNode == nullptr) {
1251 return nullptr;
1252 }
1253 keyframeAnimation->SetStartDelay(oneStageParas.delay);
1254 keyframeAnimation->SetDuration(duration);
1255 RSAnimationTimingCurve timingCurve;
1256 SymbolAnimation::CreateAnimationTimingCurve(oneStageParas.curveType, oneStageParas.curveArgs, timingCurve);
1257 std::vector<std::tuple<float, std::shared_ptr<RSPropertyBase>, RSAnimationTimingCurve>> keyframes;
1258 for (unsigned int i = 1; i < alphaPropertyStages_.size(); i++) {
1259 keyframes.push_back(std::make_tuple(timePercents[i], alphaPropertyStages_[i], timingCurve));
1260 }
1261 keyframeAnimation->AddKeyFrames(keyframes);
1262 return keyframeAnimation;
1263 }
1264
1265 // base atomizated animation
ScaleAnimationBase(const std::shared_ptr<RSNode> & rsNode,std::shared_ptr<RSAnimatableProperty<Vector2f>> & scaleProperty,const Drawing::DrawingPiecewiseParameter & scaleParameter,std::vector<std::shared_ptr<RSAnimation>> & animations)1266 void RSSymbolAnimation::ScaleAnimationBase(const std::shared_ptr<RSNode>& rsNode,
1267 std::shared_ptr<RSAnimatableProperty<Vector2f>>& scaleProperty,
1268 const Drawing::DrawingPiecewiseParameter& scaleParameter, std::vector<std::shared_ptr<RSAnimation>>& animations)
1269 {
1270 const auto& properties = scaleParameter.properties;
1271 if (properties.count(SCALE_PROP_X) <= 0 || properties.count(SCALE_PROP_Y) <= 0 ||
1272 properties.at(SCALE_PROP_X).size() < PROPERTIES ||
1273 properties.at(SCALE_PROP_Y).size() < PROPERTIES) {
1274 ROSEN_LOGD("Invalid parameter input of scale.");
1275 return;
1276 }
1277
1278 if (scaleProperty == nullptr) {
1279 SetNodePivot(rsNode);
1280 const Vector2f scaleValueBegin = { properties.at(SCALE_PROP_X).at(0), properties.at(SCALE_PROP_Y).at(0) };
1281 SymbolAnimation::CreateOrSetModifierValue(scaleProperty, scaleValueBegin);
1282 auto modifier = std::make_shared<ModifierNG::RSTransformModifier>();
1283 modifier->AttachProperty(ModifierNG::RSPropertyType::SCALE, scaleProperty);
1284 rsNode->AddModifier(modifier);
1285 }
1286
1287 const Vector2f scaleValueEnd = {properties.at(SCALE_PROP_X).at(PROP_END), properties.at(SCALE_PROP_Y).at(PROP_END)};
1288
1289 // set animation curve and protocol
1290 RSAnimationTimingCurve scaleCurve;
1291 SymbolAnimation::CreateAnimationTimingCurve(scaleParameter.curveType, scaleParameter.curveArgs, scaleCurve);
1292
1293 RSAnimationTimingProtocol scaleprotocol;
1294 if (range_.has_value()) {
1295 scaleprotocol.SetFrameRateRange(range_.value());
1296 }
1297 scaleprotocol.SetStartDelay(scaleParameter.delay);
1298 if (scaleParameter.duration > 0) {
1299 scaleprotocol.SetDuration(scaleParameter.duration);
1300 }
1301
1302 // set animation
1303 std::vector<std::shared_ptr<RSAnimation>> animations1 = RSNode::Animate(rsNode->GetRSUIContext(),
1304 scaleprotocol, scaleCurve, [&scaleProperty, &scaleValueEnd]() { scaleProperty->Set(scaleValueEnd); });
1305
1306 if (animations1.size() > 0 && animations1[0] != nullptr) {
1307 animations.emplace_back(animations1[0]);
1308 }
1309 }
1310
AlphaAnimationBase(const std::shared_ptr<RSNode> & rsNode,std::shared_ptr<RSAnimatableProperty<float>> & alphaProperty,const Drawing::DrawingPiecewiseParameter & alphaParameter,std::vector<std::shared_ptr<RSAnimation>> & animations)1311 void RSSymbolAnimation::AlphaAnimationBase(const std::shared_ptr<RSNode>& rsNode,
1312 std::shared_ptr<RSAnimatableProperty<float>>& alphaProperty,
1313 const Drawing::DrawingPiecewiseParameter& alphaParameter, std::vector<std::shared_ptr<RSAnimation>>& animations)
1314 {
1315 // validation input
1316 if (rsNode == nullptr) {
1317 ROSEN_LOGD("[%{public}s] : invalid input", __func__);
1318 return;
1319 }
1320 const auto& properties = alphaParameter.properties;
1321 if (properties.count(ALPHA_PROP) <= 0 || properties.at(ALPHA_PROP).size() < PROPERTIES) {
1322 ROSEN_LOGD("Invalid parameter input of alpha.");
1323 return;
1324 }
1325
1326 if (alphaProperty == nullptr) {
1327 float alphaValueBegin = static_cast<float>(properties.at(ALPHA_PROP).at(PROP_START));
1328 SymbolAnimation::CreateOrSetModifierValue(alphaProperty, alphaValueBegin);
1329 auto alphaModifier = std::make_shared<ModifierNG::RSAlphaModifier>();
1330 alphaModifier->AttachProperty(ModifierNG::RSPropertyType::ALPHA, alphaProperty);
1331 rsNode->AddModifier(alphaModifier);
1332 }
1333 float alphaValueEnd = static_cast<float>(properties.at(ALPHA_PROP).at(PROP_END));
1334
1335 // set animation protocol and curve
1336 RSAnimationTimingProtocol alphaProtocol;
1337 if (range_.has_value()) {
1338 alphaProtocol.SetFrameRateRange(range_.value());
1339 }
1340 alphaProtocol.SetStartDelay(alphaParameter.delay);
1341 if (alphaParameter.duration > 0) {
1342 alphaProtocol.SetDuration(alphaParameter.duration);
1343 }
1344 RSAnimationTimingCurve alphaCurve;
1345 SymbolAnimation::CreateAnimationTimingCurve(alphaParameter.curveType, alphaParameter.curveArgs, alphaCurve);
1346
1347 std::vector<std::shared_ptr<RSAnimation>> animations1 = RSNode::Animate(rsNode->GetRSUIContext(),
1348 alphaProtocol, alphaCurve, [&alphaProperty, &alphaValueEnd]() { alphaProperty->Set(alphaValueEnd); });
1349
1350 if (animations1.size() > 0 && animations1[0] != nullptr) {
1351 animations.emplace_back(animations1[0]);
1352 }
1353 }
1354
TranslateAnimationBase(const std::shared_ptr<RSNode> & rsNode,std::shared_ptr<RSAnimatableProperty<Vector2f>> & property,const Drawing::DrawingPiecewiseParameter & parameter,std::vector<std::shared_ptr<RSAnimation>> & animations)1355 void RSSymbolAnimation::TranslateAnimationBase(const std::shared_ptr<RSNode>& rsNode,
1356 std::shared_ptr<RSAnimatableProperty<Vector2f>>& property,
1357 const Drawing::DrawingPiecewiseParameter& parameter,
1358 std::vector<std::shared_ptr<RSAnimation>>& animations)
1359 {
1360 const auto& properties = parameter.properties;
1361 bool isInvalid = !properties.count(TRANSLATE_PROP_X) || !properties.count(TRANSLATE_PROP_Y) ||
1362 properties.at(TRANSLATE_PROP_X).size() < PROPERTIES ||
1363 properties.at(TRANSLATE_PROP_Y).size() < PROPERTIES;
1364 if (isInvalid) {
1365 ROSEN_LOGD("Invalid parameter input of translate.");
1366 return;
1367 }
1368
1369 if (property == nullptr) {
1370 const Vector2f valueBegin = { properties.at(TRANSLATE_PROP_X).at(0), properties.at(TRANSLATE_PROP_Y).at(0) };
1371 SymbolAnimation::CreateOrSetModifierValue(property, valueBegin);
1372 auto modifier = std::make_shared<ModifierNG::RSTransformModifier>();
1373 modifier->AttachProperty(ModifierNG::RSPropertyType::TRANSLATE, property);
1374 rsNode->AddModifier(modifier);
1375 }
1376
1377 const Vector2f valueEnd = {properties.at(TRANSLATE_PROP_X).at(PROP_END),
1378 properties.at(TRANSLATE_PROP_Y).at(PROP_END)};
1379
1380 // set animation curve and protocol
1381 RSAnimationTimingCurve timeCurve;
1382 SymbolAnimation::CreateAnimationTimingCurve(parameter.curveType, parameter.curveArgs, timeCurve);
1383
1384 RSAnimationTimingProtocol protocol;
1385 if (range_.has_value()) {
1386 protocol.SetFrameRateRange(range_.value());
1387 }
1388 protocol.SetStartDelay(parameter.delay);
1389 if (parameter.duration > 0) {
1390 protocol.SetDuration(parameter.duration);
1391 }
1392
1393 // set animation
1394 std::vector<std::shared_ptr<RSAnimation>> animations1 = RSNode::Animate(rsNode->GetRSUIContext(),
1395 protocol, timeCurve, [&property, &valueEnd]() { property->Set(valueEnd); });
1396
1397 if (animations1.size() > 0 && animations1[0] != nullptr) {
1398 animations.emplace_back(animations1[0]);
1399 }
1400 }
1401
BlurAnimationBase(const std::shared_ptr<RSNode> & rsNode,std::shared_ptr<RSAnimatableProperty<float>> & property,const Drawing::DrawingPiecewiseParameter & parameter,std::vector<std::shared_ptr<RSAnimation>> & animations)1402 void RSSymbolAnimation::BlurAnimationBase(const std::shared_ptr<RSNode>& rsNode,
1403 std::shared_ptr<RSAnimatableProperty<float>>& property,
1404 const Drawing::DrawingPiecewiseParameter& parameter,
1405 std::vector<std::shared_ptr<RSAnimation>>& animations)
1406 {
1407 const auto& properties = parameter.properties;
1408 bool isInValid = !properties.count(BLUR_PROP) || properties.at(BLUR_PROP).size() < PROPERTIES;
1409 if (isInValid) {
1410 ROSEN_LOGD("Invalid parameter input of blur.");
1411 return;
1412 }
1413
1414 if (property == nullptr) {
1415 float valueBegin = properties.at(BLUR_PROP).at(PROP_START);
1416 SymbolAnimation::CreateOrSetModifierValue(property, valueBegin);
1417 auto modifier = std::make_shared<ModifierNG::RSForegroundFilterModifier>();
1418 modifier->AttachProperty(ModifierNG::RSPropertyType::FOREGROUND_EFFECT_RADIUS, property);
1419 rsNode->AddModifier(modifier);
1420 }
1421
1422 float valueEnd = properties.at(BLUR_PROP).at(PROP_END);
1423
1424 // set animation curve and protocol
1425 RSAnimationTimingCurve timeCurve;
1426 SymbolAnimation::CreateAnimationTimingCurve(parameter.curveType, parameter.curveArgs, timeCurve);
1427
1428 RSAnimationTimingProtocol protocol;
1429 if (range_.has_value()) {
1430 protocol.SetFrameRateRange(range_.value());
1431 }
1432 protocol.SetStartDelay(parameter.delay);
1433 if (parameter.duration > 0) {
1434 protocol.SetDuration(parameter.duration);
1435 }
1436
1437 // set animation
1438 std::vector<std::shared_ptr<RSAnimation>> animations1 = RSNode::Animate(rsNode->GetRSUIContext(),
1439 protocol, timeCurve, [&property, &valueEnd]() { property->Set(valueEnd); });
1440
1441 if (animations1.size() > 0 && animations1[0] != nullptr) {
1442 animations.emplace_back(animations1[0]);
1443 }
1444 }
1445 } // namespace Rosen
1446 } // namespace OHOS