1 /*
2  * Copyright (c) 2021 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 "core/animation/animation_util.h"
17 
18 #include "bridge/common/utils/utils.h"
19 
20 namespace OHOS::Ace {
21 namespace {
22 constexpr int PARAMS_NUM = 4;
23 constexpr int INITIAL_VELOCITY = 0;
24 constexpr int DAMPING = 1;
25 constexpr int STIFFNESS = 2;
26 constexpr int MASS = 3;
27 template<class T>
ParseFunctionValue(const std::string & line,const std::string & key,std::function<T (const std::string &)> parser)28 T ParseFunctionValue(const std::string& line, const std::string& key, std::function<T(const std::string&)> parser)
29 {
30     std::vector<std::string> strs;
31     StringUtils::SplitStr(line, " ", strs, true);
32     for (const auto& str : strs) {
33         if (str.empty()) {
34             continue;
35         }
36         auto leftIndex = str.find('(');
37         auto rightIndex = str.find(')');
38         if (leftIndex == std::string::npos || rightIndex == std::string::npos) {
39             continue;
40         }
41         if (leftIndex + 1 >= rightIndex) {
42             continue;
43         }
44         if (str.substr(0, leftIndex) != key) {
45             continue;
46         }
47 
48         auto valueStr = str.substr(leftIndex + 1, rightIndex - leftIndex - 1);
49         return parser(valueStr);
50     }
51     return T {};
52 }
53 
GetTransformTypeValue(const std::unique_ptr<JsonValue> & transformJson)54 std::string GetTransformTypeValue(const std::unique_ptr<JsonValue>& transformJson)
55 {
56     if (transformJson->IsNull()) {
57         LOGE("transformJson is null");
58         return "";
59     }
60     std::string jsonValue = transformJson->GetString();
61     if (jsonValue.empty()) {
62         double jsonDouble = transformJson->GetDouble();
63         return std::to_string(jsonDouble);
64     }
65     return jsonValue;
66 }
67 
GetTransformType(const std::unique_ptr<JsonValue> & transformJson)68 std::string GetTransformType(const std::unique_ptr<JsonValue>& transformJson)
69 {
70     if (transformJson->IsNull()) {
71         LOGE("transformJson is null");
72         return "";
73     }
74     return transformJson->GetKey();
75 }
76 
77 } // namespace
78 
ParseAnimationStyle(const std::vector<std::unordered_map<std::string,std::string>> & animationKeyframes,const RefPtr<Declaration> & declaration,const RefPtr<ThemeConstants> themeConstants)79 void AnimationUtil::ParseAnimationStyle(
80     const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes,
81     const RefPtr<Declaration>& declaration, const RefPtr<ThemeConstants> themeConstants)
82 {
83     if (declaration) {
84         isRightToLeft = declaration->IsRightToLeft();
85     }
86     themeConstants_ = themeConstants;
87 
88     Clear();
89 
90     for (const auto& animationNameKeyframe : animationKeyframes) {
91         auto animationName = animationNameKeyframe.find(DOM_ANIMATION_NAME);
92         if (animationName != animationNameKeyframe.end()) {
93             animationName_ = animationName->second;
94             if (declaration) {
95                 auto& animationStyle =
96                     declaration->MaybeResetStyle<CommonAnimationStyle>(StyleTag::COMMON_ANIMATION_STYLE);
97                 if (animationStyle.IsValid()) {
98                     animationStyle.animationOperation = AnimationOperation::PLAY;
99                 }
100             }
101             continue;
102         }
103 
104         // time from keyframe; offset from js api
105         auto pos = animationNameKeyframe.find(DOM_ANIMATION_NAME_TIME);
106         if (pos == animationNameKeyframe.end()) {
107             pos = animationNameKeyframe.find(DOM_ANIMATION_OFFSET);
108         }
109         if (pos == animationNameKeyframe.end()) {
110             continue;
111         }
112         auto timeStr = pos->second;
113         if (timeStr.empty()) {
114             continue;
115         }
116 
117         for (const auto& [keyStyle, value] : animationNameKeyframe) {
118             if (keyStyle == DOM_ANIMATION_NAME_TIME || keyStyle == DOM_ANIMATION_OFFSET) {
119                 continue;
120             }
121             KeyframesAddKeyFrame(keyStyle, value, timeStr);
122         }
123     }
124     if (!shadowKeyframes_.empty()) {
125         for (auto&& [key, shadow] : shadowKeyframes_) {
126             double time = StringUtils::StringToDouble(key) / 100.0;
127             AddAnimatable(shadow, time, AnimatableType::PROPERTY_BOX_SHADOW);
128         }
129     }
130 }
131 
KeyframesAddKeyFrame(const std::string & keyStyle,const std::string & value,const std::string & timeStr)132 void AnimationUtil::KeyframesAddKeyFrame(
133     const std::string& keyStyle, const std::string& value, const std::string& timeStr)
134 {
135     static const std::unordered_map<std::string,
136         void (*)(const std::string&, const double&, const std::string&, AnimationUtil&)>
137         keyFrameAddMap = {
138             { DOM_BACKGROUND_COLOR,
139                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
140                     util.AddAnimatable(util.ParseColor(value), time, AnimatableType::PROPERTY_BG_COLOR);
141                 } },
142             { DOM_BACKGROUND_IMAGE_SIZE,
143                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
144                     BackgroundImageSize backgroundImageSize;
145                     if (!Framework::ParseBackgroundImageSize(value, backgroundImageSize)) {
146                         LOGW("ParseBackgroundImageSize failed.");
147                         return;
148                     }
149                     util.AddAnimatable(backgroundImageSize, time, AnimatableType::PROPERTY_BACKGROUND_SIZE);
150                 } },
151             { DOM_BACKGROUND_IMAGE_POSITION,
152                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
153                     BackgroundImagePosition backgroundImagePosition;
154                     if (!Framework::ParseBackgroundImagePosition(value, backgroundImagePosition)) {
155                         LOGW("ParseBackgroundImagePosition failed.");
156                         return;
157                     }
158                     util.AddAnimatable(backgroundImagePosition, time, AnimatableType::PROPERTY_BACKGROUND_POSITION);
159                 } },
160             { DOM_WIDTH,
161                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
162                     LOGE("DOM_WIDTH:%{public}s time:%{public}lf", value.c_str(), time);
163                     util.AddAnimatable(util.ParseDimension(value), time, AnimatableType::PROPERTY_WIDTH);
164                 } },
165             { DOM_HEIGHT,
166                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
167                     util.AddAnimatable(util.ParseDimension(value), time, AnimatableType::PROPERTY_HEIGHT);
168                 } },
169             { DOM_OPACITY,
170                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
171                     util.AddAnimatable<float>(util.ParseDouble(value), time, AnimatableType::PROPERTY_OPACITY);
172                 } },
173             // margin
174             { DOM_MARGIN_LEFT,
175                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
176                     util.AddAnimatable(
177                         util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_LEFT);
178                 } },
179             { DOM_MARGIN_RIGHT,
180                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
181                     util.AddAnimatable(
182                         util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_RIGHT);
183                 } },
184             { DOM_MARGIN_TOP,
185                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
186                     util.AddAnimatable(
187                         util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_TOP);
188                 } },
189             { DOM_MARGIN_BOTTOM,
190                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
191                     util.AddAnimatable(
192                         util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_BOTTOM);
193                 } },
194             { DOM_MARGIN_START,
195                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
196                     if (util.isRightToLeft) {
197                         util.AddAnimatable(
198                             util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_RIGHT);
199                     } else {
200                         util.AddAnimatable(
201                             util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_LEFT);
202                     }
203                 } },
204             { DOM_MARGIN_END,
205                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
206                     if (util.isRightToLeft) {
207                         util.AddAnimatable(
208                             util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_LEFT);
209                     } else {
210                         util.AddAnimatable(
211                             util.ParseDimension(value), time, AnimatableType::PROPERTY_MARGIN_RIGHT);
212                     }
213                 } },
214             { DOM_MARGIN,
215                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
216                     auto margin = util.ParseDimension(value);
217                     util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_LEFT);
218                     util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_TOP);
219                     util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_RIGHT);
220                     util.AddAnimatable(margin, time, AnimatableType::PROPERTY_MARGIN_BOTTOM);
221                 } },
222             // padding
223             { DOM_PADDING_LEFT,
224                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
225                     util.AddAnimatable(
226                         util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_LEFT);
227                 } },
228             { DOM_PADDING_RIGHT,
229                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
230                     util.AddAnimatable(
231                         util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_RIGHT);
232                 } },
233             { DOM_PADDING_TOP,
234                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
235                     util.AddAnimatable(
236                         util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_TOP);
237                 } },
238             { DOM_PADDING_BOTTOM,
239                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
240                     util.AddAnimatable(
241                         util.ParseDimension(value), time, AnimatableType::PROPERTY_PADDING_BOTTOM);
242                 } },
243             { DOM_PADDING_START,
244                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
245                     auto padding = util.ParseDimension(value);
246                     if (util.isRightToLeft) {
247                         util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_RIGHT);
248                     } else {
249                         util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_LEFT);
250                     }
251                 } },
252             { DOM_PADDING_END,
253                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
254                     auto padding = util.ParseDimension(value);
255                     if (util.isRightToLeft) {
256                         util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_LEFT);
257                     } else {
258                         util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_RIGHT);
259                     }
260                 } },
261             { DOM_PADDING,
262                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
263                     auto padding = util.ParseDimension(value);
264                     util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_LEFT);
265                     util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_TOP);
266                     util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_RIGHT);
267                     util.AddAnimatable(padding, time, AnimatableType::PROPERTY_PADDING_BOTTOM);
268                 } },
269             // border
270             { DOM_BORDER_LEFT_WIDTH,
271                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
272                     util.AddAnimatable<float>(
273                         util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_LEFT_WIDTH);
274                 } },
275             { DOM_BORDER_RIGHT_WIDTH,
276                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
277                     util.AddAnimatable<float>(
278                         util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_RIGHT_WIDTH);
279                 } },
280             { DOM_BORDER_TOP_WIDTH,
281                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
282                     util.AddAnimatable<float>(
283                         util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_TOP_WIDTH);
284                 } },
285             { DOM_BORDER_BOTTOM_WIDTH,
286                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
287                     util.AddAnimatable<float>(
288                         util.ParseDouble(value), time, AnimatableType::PROPERTY_BORDER_BOTTOM_WIDTH);
289                 } },
290             { DOM_BORDER_WIDTH,
291                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
292                     auto borderWidth = util.ParseDouble(value);
293                     util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_LEFT_WIDTH);
294                     util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_RIGHT_WIDTH);
295                     util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_TOP_WIDTH);
296                     util.AddAnimatable<float>(borderWidth, time, AnimatableType::PROPERTY_BORDER_BOTTOM_WIDTH);
297                 } },
298             { DOM_BORDER_RADIUS,
299                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
300                     auto radius = util.ParseDouble(value);
301                     util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_LEFT_RADIUS);
302                     util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_RIGHT_RADIUS);
303                     util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_LEFT_RADIUS);
304                     util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS);
305                 } },
306             { DOM_BORDER_TOP_LEFT_RADIUS,
307                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
308                     auto radius = util.ParseDouble(value);
309                     util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_LEFT_RADIUS);
310                 } },
311             { DOM_BORDER_TOP_RIGHT_RADIUS,
312                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
313                     auto radius = util.ParseDouble(value);
314                     util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_TOP_RIGHT_RADIUS);
315                 } },
316             { DOM_BORDER_BOTTOM_LEFT_RADIUS,
317                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
318                     auto radius = util.ParseDouble(value);
319                     util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_LEFT_RADIUS);
320                 } },
321             { DOM_BORDER_BOTTOM_RIGHT_RADIUS,
322                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
323                     auto radius = util.ParseDouble(value);
324                     util.AddAnimatable<float>(radius, time, AnimatableType::PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS);
325                 } },
326             { DOM_BORDER_LEFT_COLOR,
327                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
328                     auto color = util.ParseColor(value);
329                     util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_LEFT_COLOR);
330                 } },
331             { DOM_BORDER_RIGHT_COLOR,
332                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
333                     auto color = util.ParseColor(value);
334                     util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_RIGHT_COLOR);
335                 } },
336             { DOM_BORDER_TOP_COLOR,
337                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
338                     auto color = util.ParseColor(value);
339                     util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_TOP_COLOR);
340                 } },
341             { DOM_BORDER_BOTTOM_COLOR,
342                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
343                     auto color = util.ParseColor(value);
344                     util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_BOTTOM_COLOR);
345                 } },
346             { DOM_BORDER_COLOR,
347                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
348                     auto color = util.ParseColor(value);
349                     util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_LEFT_COLOR);
350                     util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_TOP_COLOR);
351                     util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_RIGHT_COLOR);
352                     util.AddAnimatable<Color>(color, time, AnimatableType::PROPERTY_BORDER_BOTTOM_COLOR);
353                 } },
354             { DOM_BORDER_LEFT_STYLE,
355                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
356                     auto borderStyle = Framework::ConvertStrToBorderStyle(value);
357                     util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_LEFT_STYLE);
358                 } },
359             { DOM_BORDER_RIGHT_STYLE,
360                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
361                     auto borderStyle = Framework::ConvertStrToBorderStyle(value);
362                     util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_RIGHT_STYLE);
363                 } },
364             { DOM_BORDER_TOP_STYLE,
365                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
366                     auto borderStyle = Framework::ConvertStrToBorderStyle(value);
367                     util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_TOP_STYLE);
368                 } },
369             { DOM_BORDER_BOTTOM_STYLE,
370                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
371                     auto borderStyle = Framework::ConvertStrToBorderStyle(value);
372                     util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_BOTTOM_STYLE);
373                 } },
374             { DOM_BORDER_STYLE,
375                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
376                     auto borderStyle = Framework::ConvertStrToBorderStyle(value);
377                     util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_LEFT_STYLE);
378                     util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_TOP_STYLE);
379                     util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_RIGHT_STYLE);
380                     util.AddAnimatable<BorderStyle>(borderStyle, time, AnimatableType::PROPERTY_BORDER_BOTTOM_STYLE);
381                 } },
382             { DOM_FILTER,
383                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
384                     auto radius = ParseFunctionValue<Dimension>(value, DOM_BLUR, Framework::StringToDimension);
385                     if (GreatOrEqual(radius.Value(), 0.0)) {
386                         util.AddAnimatable<float>(
387                             static_cast<float>(radius.Value()), time, AnimatableType::PROPERTY_FILTER_BLUR);
388                     }
389                 } },
390             { DOM_BACKDROP_FILTER,
391                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
392                     auto radius = ParseFunctionValue<Dimension>(value, DOM_BLUR, Framework::StringToDimension);
393                     if (GreatOrEqual(radius.Value(), 0.0)) {
394                         util.AddAnimatable<float>(
395                             static_cast<float>(radius.Value()), time, AnimatableType::PROPERTY_BACKDROP_FILTER_BLUR);
396                     }
397                 } },
398             { DOM_WINDOW_FILTER,
399                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
400                     std::vector<std::string> offsets;
401                     StringUtils::StringSplitter(value, ' ', offsets);
402                     // property animation only support progress
403                     if (!offsets.empty()) {
404                         auto progress =
405                             ParseFunctionValue<Dimension>(offsets[0], DOM_BLUR, Framework::StringToDimension);
406                         if (progress.Unit() == DimensionUnit::PERCENT) {
407                             if (GreatOrEqual(progress.Value(), 0.0) && LessOrEqual(progress.Value(), 1.0)) {
408                                 util.AddAnimatable<float>(static_cast<float>(progress.Value()), time,
409                                     AnimatableType::PROPERTY_WINDOW_FILTER_BLUR);
410                             }
411                         }
412                     }
413                 } },
414             // BoxShadow
415             { DOM_BOX_SHADOW_H,
416                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
417                     auto& shadow = util.shadowKeyframes_[timeStr];
418                     shadow.SetOffsetX(util.ParseDouble(value));
419                 } },
420             { DOM_BOX_SHADOW_V,
421                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
422                     auto& shadow = util.shadowKeyframes_[timeStr];
423                     shadow.SetOffsetY(util.ParseDouble(value));
424                 } },
425             { DOM_BOX_SHADOW_BLUR,
426                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
427                     auto& shadow = util.shadowKeyframes_[timeStr];
428                     shadow.SetBlurRadius(util.ParseDouble(value));
429                 } },
430             { DOM_BOX_SHADOW_SPREAD,
431                 [](const std::string& value, const double& time,  const std::string& timeStr, AnimationUtil& util) {
432                     auto& shadow = util.shadowKeyframes_[timeStr];
433                     shadow.SetSpreadRadius(util.ParseDouble(value));
434                 } },
435             { DOM_BOX_SHADOW_COLOR,
436                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
437                     auto& shadow = util.shadowKeyframes_[timeStr];
438                     shadow.SetColor(util.ParseColor(value));
439                 } },
440             // position
441             { DOM_POSITION_LEFT,
442                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
443                     util.AddAnimatable(
444                         util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_LEFT);
445                 } },
446             { DOM_POSITION_TOP,
447                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
448                     util.AddAnimatable(
449                         util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_TOP);
450                 } },
451             { DOM_POSITION_RIGHT,
452                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
453                     util.AddAnimatable(
454                         util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_RIGHT);
455                 } },
456             { DOM_POSITION_BOTTOM,
457                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
458                     util.AddAnimatable(
459                         util.ParseDimension(value), time, AnimatableType::PROPERTY_POSITION_BOTTOM);
460                 } },
461             { DOM_TRANSFORM,
462                 [](const std::string& value, const double& time, const std::string& timeStr, AnimationUtil& util) {
463                     std::unique_ptr<JsonValue> transformJson = JsonUtil::ParseJsonString(value);
464                     if (transformJson->GetArraySize() == 0) {
465                         // when empty should insert an identity matrix.
466                         util.transformConvertor_.InsertIdentityKeyframe(time);
467                     }
468                     for (int32_t index = 0; index < transformJson->GetArraySize(); ++index) {
469                         std::string typeKey = GetTransformType(transformJson->GetArrayItem(index));
470                         std::string typeValue = GetTransformTypeValue(transformJson->GetArrayItem(index));
471                         if ((!typeKey.empty()) && (!typeValue.empty())) {
472                             util.transformConvertor_.Convert(typeKey, typeValue, time);
473                         }
474                     }
475                 } },
476         };
477     auto pos = keyFrameAddMap.find(keyStyle);
478     if (pos != keyFrameAddMap.end()) {
479         double time = StringUtils::StringToDouble(timeStr) / 100.0;
480         pos->second(value, time, timeStr, *this);
481     }
482 }
483 
CreateKeyboardAnimationOption(const KeyboardAnimationConfig & config,float keyboardHeight)484 AnimationOption AnimationUtil::CreateKeyboardAnimationOption(
485     const KeyboardAnimationConfig& config, float keyboardHeight)
486 {
487     static const LinearMapNode<RefPtr<Curve>> curveMap[] = {
488         { "ease", Curves::EASE },
489         { "easeIn", Curves::EASE_IN },
490         { "easeInOut", Curves::EASE_IN_OUT },
491         { "easeOut", Curves::EASE_OUT },
492         { "default", Curves::EASE_IN_OUT },
493         { "linear", Curves::LINEAR },
494         { "spring", AceType::MakeRefPtr<ResponsiveSpringMotion>(ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_RESPONSE,
495                         ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_DAMPING_RATIO,
496                         ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_BLEND_DURATION) },
497         { "interactiveSpring", AceType::MakeRefPtr<ResponsiveSpringMotion>(
498                                    ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_RESPONSE,
499                                    ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_DAMPING_RATIO,
500                                    ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_BLEND_DURATION) },
501     };
502 
503     AnimationOption option;
504     auto curveConfig = NearZero(keyboardHeight) ? config.curveOut_ : config.curveIn_;
505     option.SetDuration(curveConfig.duration_);
506     RefPtr<Curve> curve;
507     if (curveConfig.curveType_ == "cubic" && curveConfig.curveParams_.size() == PARAMS_NUM) {
508         // cubic curve needs 4 params
509         curve = AceType::MakeRefPtr<CubicCurve>(
510             curveConfig.curveParams_[INITIAL_VELOCITY], curveConfig.curveParams_[DAMPING],
511             curveConfig.curveParams_[STIFFNESS], curveConfig.curveParams_[MASS]);
512     } else if (curveConfig.curveType_ == "interpolatingSpring" && curveConfig.curveParams_.size() == PARAMS_NUM) {
513         // interpolatingSpring needs 4 params
514         curve = AceType::MakeRefPtr<InterpolatingSpring>(
515             curveConfig.curveParams_[INITIAL_VELOCITY], curveConfig.curveParams_[DAMPING],
516             curveConfig.curveParams_[STIFFNESS], curveConfig.curveParams_[MASS]);
517     } else {
518         auto index = BinarySearchFindIndex(curveMap, ArraySize(curveMap), curveConfig.curveType_.c_str());
519         curve = index < 0 ? nullptr : curveMap[index].value;
520     }
521     option.SetCurve(curve);
522     return option;
523 }
524 
525 template<class T>
AddAnimatable(const T & value,double time,AnimatableType type)526 void AnimationUtil::AddAnimatable(const T& value, double time, AnimatableType type)
527 {
528     auto animatable = AceType::MakeRefPtr<AnimatableData<T>>(value);
529     animatable->SetTimePoint(time);
530     auto it = propAnimationMap_.find(type);
531     if (it == propAnimationMap_.end()) {
532         auto animation = AceType::MakeRefPtr<PropertyAnimation>(type);
533         animation->AddAnimatable(animatable);
534         propAnimationMap_.emplace(type, animation);
535         return;
536     }
537     it->second->AddAnimatable(animatable);
538 }
539 
GetThemeConstants() const540 RefPtr<ThemeConstants> AnimationUtil::GetThemeConstants() const
541 {
542     return themeConstants_;
543 }
544 
ParseColor(const std::string & value,uint32_t maskAlpha) const545 Color AnimationUtil::ParseColor(const std::string& value, uint32_t maskAlpha) const
546 {
547     auto&& noRefFunc = [&value, maskAlpha = maskAlpha]() { return Color::FromString(value, maskAlpha); };
548     auto&& idRefFunc = [constants = themeConstants_](uint32_t refId) { return constants->GetColor(refId); };
549     if (!themeConstants_) {
550         noRefFunc();
551     }
552     return ParseThemeReference<Color>(value, noRefFunc, idRefFunc, Color::TRANSPARENT);
553 }
554 
ParseDouble(const std::string & value) const555 double AnimationUtil::ParseDouble(const std::string& value) const
556 {
557     auto&& noRefFunc = [&value]() { return StringUtils::StringToDouble(value); };
558     auto&& idRefFunc = [constants = themeConstants_](uint32_t refId) { return constants->GetDouble(refId); };
559     if (!themeConstants_) {
560         noRefFunc();
561     }
562     return ParseThemeReference<double>(value, noRefFunc, idRefFunc, 0.0);
563 }
564 
ParseDimension(const std::string & value) const565 Dimension AnimationUtil::ParseDimension(const std::string& value) const
566 {
567     auto&& noRefFunc = [&value]() { return StringUtils::StringToDimension(value); };
568     auto&& idRefFunc = [constants = themeConstants_](uint32_t refId) { return constants->GetDimension(refId); };
569     if (!themeConstants_) {
570         noRefFunc();
571     }
572     return ParseThemeReference<Dimension>(value, noRefFunc, idRefFunc, Dimension());
573 }
574 
575 } // namespace OHOS::Ace
576