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